Coding a basic Java application
Most of the time, when you are working on a Java application you are not starting from scratch. You have to integrate your code in an existing project or you wish to use an existing framework and as such, your main problem is working with an existing piece of code. We will see how we can use Eclipse to help us write, fix and navigate in our code with, among other features, code completion, quick fixes, automatic imports, search and code templates. This post will start slowly as the most important tips will be explained first so I will take some time to detail their behavior.
Let’s consider the following use case. You are working on a brand new piece of code that depends on an existing Java application. It can be a library, a framework or an existing project. You have read the documentation, you saw a blog post about a nice piece of code or one of your coworkers gave you some information to start. In our case we will consider that our goal is to use the framework EMF to “load a resource from a file using a resource set and then navigate inside the content of the resource to display the properties of the attributes it may contain”. You are not familiar with the EMF framework? Perfect! From this description of the problem, we have an indication on the dependencies that we should use (some EMF jar files) and we know the concepts to use in order to start. We need a file, a resource and a resource set (whatever that is).
We have seen in the previous post how to add dependencies to a Java project. I have already added all the necessary jars from EMF in my Java project before. Now, let’s start coding. From what we have heard, we need to start with a file and a resource set but while I know where to find this “file” (java.io.File), where can I find this concept of resource set?
2.1 - Looking for code
In the Java Development Toolkit, when you are looking for a type, you should use the “open type” action. You can find it on your toolbar in the Java perspective or by using “Ctrl+Shift+T” . It opens a dialog box that let you search for any Java type in your workspace or in the dependencies of the content of your workspace (you can expand where Eclipse should look but we will see that later). This dialog box is also leveraging the power of the Java naming convention to speed up your search. This is a very important concept in the Java tooling in Eclipse.
Java uses camel case as a naming convention and as such this concept of “resource set” can pretty much only be written as “ResourceSet”. When you are using / importing / looking for / instantiating / manipulating a concept in Java, you do not have to write everything. If you are writing more than 50% of the code displayed on the screen, you are doing a bad job! Since I am looking for the concept of ResourceSet, I will only type “RS” in the search field of the “Open Type” dialog. There are lots of entities that contains both of those upper cased letters in this order (like RelationServiceNotRegisteredException) so I will filter the result a bit by adding precising a bit more what I am looking for by typing “RSet”. Eclipse can then easily find the type “ResourceSet” that I was looking for. I can see, at the bottom of the dialog, in which jar this concept is located and I know in which package it is defined. Here, we can see that it is located in the package “org.eclipse.emf.ecore.resource”, which seems right. By clicking on “OK”, this type will be opened in a new editor.
2.2 - Attach the sources
As you can see it, an editor is now opened on the type ResourceSet by I can only look at the bytecode. I can’t see the source code. After a quick search on the web, I have found the jars containing the source code. I can put them in my lib folder and then I can use the “Attach Source” button to open a popup which will let you select where the source code is located. I have used this popup to link the jar of “org.eclipse.emf.ecore” to the jar containing its source code “org.eclipse.emf.ecore.source”. As a result, the editor now shows the source code of “ResourceSet”.
2.3 - Camel case and code completion
Now, we have found the concept of resource set that we were looking for and we have read its javadoc to know what we are dealing with. Let’s start coding for real. I want an instance of ResourceSet, so let’s start by creating one. The first thing you would be writing is “ResourceSet resourceSet = <something>”. As I said before, you should not write everything by yourself and you should leverage the massive use of camel case. As such, you should not write “ResourceSet resourceSet” by yourself, you should type “RSet” and use the code completion (Ctrl+Space). As a result, the type ResourceSet is imported and “ResourceSet” is written. You now have to type the name of the variable. Unless you have specific reasons, you should let Eclipse choose the name of your variables for you. For an instance of the type ResourceSet, Eclipse let you choose between “resourceSet” and “set”. Let’s choose “resourceSet”. Now we have typed “ResourceSet resourceSet” and we have imported the type ResourceSet just by typing in reality “RSet ” and by using the code completion. Among the valid reasons to not use the name given by the code completion, we can find:
you already have a variable with the same name and “<variableName>2” is a very bad name. your variable carry a very specific meaning that cannot be discovered just by its typeFor those use cases, all you need to do is to add a prefix or a suffix to the name suggested by Eclipse like “inputResourceSet” or “outputResourceSet”. But in order to have a code which is easy to maintain and fast to write, you really need a good reason not to use one of the name suggested by Eclipse.
Now that we have “ResourceSet resourceSet”, let’s create an instance of resource set. We manually type ” = new ” to have “ResourceSet resourceSet = new ” but now we have another problem, ResourceSet is an interface so how do we find an instance of ResourceSet?
2.4 - Navigate in the hierarchy of your code
How do we find all the implementations of ResourceSet? You have several ways of navigating the hierarchy of your code in Eclipse. First, you can open once again the source code of “ResourceSet” by using “F3” or “Ctrl+click” on the type “ResourceSet” (“Ctrl” will transform any navigable element into a hyperlink). Once the type “ResourceSet” is opened, you can have a look at the documentation to find a potential implementation but sometimes you won’t find any information there. You may be able to re-use the “link with editor” action from the Package Explorer view, seen in the first post, to navigate directly inside of the jar to look for implementation but it’s boring.
If you really want to see the hierarchy of your code, you can use the “Code Hierarchy” view by using “F4”. With this view, you can see all the types that are extending or implementing “ResourceSet”, you can also see which type “ResourceSet” is extending or implementing itself. We can see here that we have a class named “ResourceSetImpl” that implements “ResourceSet”. There is another way to navigate in the hierarchy of your code using “Ctrl+T” on a type or a method. This shortcut will give you the list of all the type that are extending the selected type or all the types that are overriding a selected method. You don’t even have to leave your code to use it. Those two ways of navigating the hierarchy of your code are confirming what we believed, we need to use “ResourceSetImpl”. In order to do that, we just write “RSI” and use the code completion.
We now have “ResourceSet resourceSet = new ResourceSetImpl()” and both “ResourceSet” and “ResourceSetImpl” have been properly imported. We just need to add the final “;” and our first line of code has been written. Yet, we have just typed “RSet = new RSI;”
2.5 - Quick fix and code completion
Now that we have seen how we can use the Java naming conventions, code completion and the code navigation to find what we want, we have created an instance of “ResourSet”. We know from the instructions at the beginning of the post that we need a file. Just by typing “Fil = new ;” we can instantiate a new Java file thanks to the code completion.
We have our file and we have our resource set so how do we combine those two entities to get a resource? The easiest way to do this is to start using your “resourceSet” with the code completion to see the available operations. For that, you just have to type “rS” and use the code completion to obtain “resourceSet” and then “.”. The code completion gives you access to all the available methods on “ResourceSet”. You quickly realize that the method “getResource(URI uri, boolean loadOnDemand)” seems to match what you were looking for. You can type with method by typing “gR”.
Now that we have “resourceSet.getResource(uri, loadOnDemand);”, we have two problems, “uri” and “loadOnDemand” are not matching any existing variables. While we know what “loadOnDemand” represents since “boolean” is a known type, we don’t know what “uri” is. Is it a “java.net.URI” or a “com.sun.org.apache.xml.internal.zerializer.utils.URI”? This is where your next best friend enters into action, the quick fix! You just need to place your cursor at the end of line (where it should be anyway after typing the “;”) and use “Ctrl+1”. The quick fix action can create the boolean “loadOnDemand” for you but after that you still have an error, you don’t have an uri. by using the quick fix once again, the variable uri is created and the type URI (from org.eclipse.emf.common.util) is properly imported.
Now that this is fixed, you still have two errors, both newly created variables are not initialized. By using the quick fix again, you can initialize them easily. Now the boolean “loadOnDemand” is initialized to “false” (we will change that to true) and “uri” is initialized to “null”. One last step, we need to retrieve the result of the call to “getResource”. For that, keep your cursor at the end of the line and use quick fix once again, you can create easily the variable that will hold the result of the call to “getResource” and the import of the type “Resource” will be realized for you. By typing “rS.gR;” and using the completion and the quick fix we now have “Resource resource = resourceSet.getResource(uri, loadOnDemand);” with all the necessary types imported and the variables created, named and initialized. I’ll say it again but if you are writing all your code manually, you are doing a bad job!
2.6 - Automatic imports and organize imports
We have seen how we can use the code completion and the quick fix to speed up our development and we’ve seen how they can automatically import the necessary dependencies for us but sometimes you will copy a piece of code from a forum and when you will paste it in your code. It won’t compile since you don’t have the necessary imports. Let’s delete all the import realized previously. If you need to force Eclipse to resolve the import for you, you just need to use the shortcut “Ctrl+Shift+O”, in case of conflict (they are several types named URI for example), a popup will appear to give you the opportunity to choose which type to use. The imports will be written and ordered.
2.7 - Look for the features of your type
We now have our file, our resource set and we have seen how we can get a resource from the resource set but one thing is missing, where do we find this “uri” that we need? Right now, it is initialized with “null” and we know that it won’t really work. By using the quick navigation (Ctrl+click) we can open the class URI. Since it is a class, we only need to look for its constructor. In order to do that, you can use the outline view or you can use the shortcut “Ctrl+o” to open a popup showing all the fields and methods of the class.
When the popup opened from using “Ctrl+o” is displayed, you can also see inside the inherited methods and fields by pressing “Ctrl+o” a second time (since URI does not inherit from anyone it would be pointless here). By using the camel case, you can quickly find what you are looking for, here we need a constructor so we are looking for “URI”. Unfortunately for us, we see that the constructor of URI is private so we can’t use it. So how can we create our URI?
2.8 - Where is my code called from?
If we can’t use the constructor of URI, let’s see where it is called from. Eclipse can let you see where a given piece of code is called from very easily, you just have to place your cursor on a piece of code and use “Ctrl+Alt+H”. This shortcut will open the “Call Hierarchy” view where you can navigate in all the code that is using the selected element. Here we can see that the constructor of URI is used by a lot of operations. By navigating in the “Call Hierarchy” view, we can see that the static method “createFileURI” is using this private constructor indirectly and from its javadoc it seems to take the absolute path of a file and it returns the matching URI. We already have our file, this method will be perfect for us.
2.9 - Coding templates
We want to have a look at the content of this newly loaded resource, for that, we create a variable with the content of the resource (List<EObject> contents = resource.getContents();). Now we want to iterate on this content and display something for each element. We could write a “for” block manually but Eclipse provides a lot of code templates to help you code faster. As such, you just need to type “foreach” on the following line and use the code completion. The “for” block is then automatically created for you. There are lots of code templates available in Eclipse from “sysout” to “toarray”, “try”, “new”, “nls” or even “arrayadd” to add an element to an array. In the next post we will see how you can customize those templates and even create new ones. Do not forget that you have access to code completion and code templates in the javadoc too.
2.10 - Format and indent
Eclipse also give you the ability to format your code with the “Ctrl+Shift+f” action. You can also indent your code with the shortcut “Ctrl+i”. Since our code was properly formatted and indented since the beginning, it won’t make any difference for us but it is quite useful when copying code from internet.
In this post, I’ve spent a lot of time detailing precisely the behavior of the most powerful and the most commonly used tips to speed up your Java development in Eclipse. Next time, I’ll go faster to explain advanced features of the Java Development Toolkit.