Java: Proper organization of external libraries? - java

So I took a Coursera course that had me work with external libraries. Two .jar files which most of the weekly projects depended upon.
I'm not entirely sure how eclipse compiles and runs the files, and how it links to these external libraries -- what is the proper way of organizing this? Do I put a copy of each .jar file in each project directory?
Is there another, cleaner way that I should be organizing this?
Thanks --

As a beginner programmer it is OK to put it in each project. But consider that this is ongoing work and at some time in future you want to upgrade to a new version of these external libraries. Then you would have to copy it everywhere.
Instead another option is to store them in one place and add it in classpath in each project. Now you have only one copy of it, which is always better.
Now, if and when you do get a new version then the file names might change, so you will still have to change the classpath of each project.
But I advise you to worry about these and other such problems later. For now, focus on programming related problems rather than configuration.

If you want to maintain your libraries professionally in a formal manor then you're better of using a build tool like Gradle of Maven.
I'd suggest you to use Gradle to maintain the project since it has a whole lot of useful build tools available to you to use. Eclipse has a Gradle plugin available which allows you to use Gradle projects with it. See link below.
To give you a idea of how Gradle is used professionally. Android uses it by default to maintain their projects now. So Android java projects uses the Gradle build tool to maintain its library sources, compilation processes and such.
The difference between a Gradle project and a normal java project is that a Gradle project has a list of pre-defined scripts available to you which fetches the libraries, compiles them and prepares them before exporting the final bundle (jar). So really all Gradle does in before hand is fetch the libraries and prepares the specified tools before compilation so you won't need to mess with them your self. It prepares your project directory and remotely maintains your libraries so if they're available from a repository then it'll make sure to prepare them appropriately in before hand and setup your projects directories.
So really the difference you'd physically notice is that instead of using the default Eclipse export button to create your bundle (jar) you'd instead use a button from the side menu which the Gradle plugin adds and also you'd cleanly list the libraries in a structured order in a file that gets added to your project root.
If you want to get a basic understanding of how it works and really want to start to proffesionally or formally structure your project then try to create a very basic android app in Android Studio. see link below
If this isn't what you want at all and don't want to take it to this advanced level yet then adding the library bundles into some kind of lib folder that's located in your project root is properly best practice.
If you wonder why? Well basically different projects might use different versions of the library which may add or remove support to them. So to keep the versions consistent and make sure to have the right version available to you, you have the direct source near the project it self.
Here's some useful link:
http://www.vogella.com/tutorials/EclipseGradle/article.html
http://developer.android.com/sdk/index.html

Related

Using a Library in Source Code in Eclipse?

It's been about 6 years since I had to do any Java programming, and even longer since I had to do any notable amount of Java programming. While I remember the language, I was always weak on all the other things, such as all the tools for building programs and such. In fact, I've forgotten more than I remember - and I was self taught in the first place.
In the past I based my organization of code on what I had seen in some open source projects, so I had directories set up with something like com/mybiz/util and com/mybiz/network and so on. I'd put the source code for the classes in the appropriate directory and make sure it was in the package that matched that path. Then if I had to change the code (like for a bug fix or to add a new routine in an existing class), it was easy for me - change it and recompile the class. As I recall, imports for the classes in the root directory for my project (it was all tied together) to use these classes were no problem with that setup.
Then someone told me about Eclipse, but the biggest thing I remember doing was refactoring in it. Until then, my IDE was a console window and a text editor.
So I still have a lot of classes in that hierarchy - com/mybiz/util (and so on). But now I'm using this code for personal libraries, so it's in com/tango/util and com/tango/network and such. I've having to make changes here and there to code to make it more universal and to remove stuff that was specific to the business for one reason or another.
I want to use these classes as libraries for my projects in Eclipse now. I'd rather not just compile and put them all into a jar, since many of the classes are still being fine tuned and need recompiling. I'd rather just be able to tell Eclipse, "Use this bundle of source code in the "com/tango..." directory tree and then just use something like "import com.tango.util.FileUtils" in my source code.
Even more, I'd like to be able to specify this as a library or some kind of available source code or resource in Eclipse so it's easily added (or added by default) to each project I create.
Can I do this? Or should I be looking into something else or another way to handle it instead? Again, I'd rather just have the source code included, since it's still being changed around and being recompiled.
For the refactoring "magic" you want to use Eclipse needs to know all source files to execute, so you have to have all your source code added into an Eclipse Java project.
However, if you want to have a set of classes that are available for multiple projects, nobody stops you from creating multiple projects, and setting up dependencies between them. The easiest way to achieve this is to add a dependency in the New Java Project wizard (be careful not to press the finish button after setting up the project name but use the Next button where you can add existing Java projects into the build path).
If all your source code is available in either a single, or some interdependent Eclipse Java projects, then Eclipse will take care of compiling all the classes. Usually, Eclipse is intelligent enough to only recompile what needs to be changed, so this process is really swift (at least most of the time).
I hope this answer is helpful enough - if not, feel free to ask for further information.
Edit: Adding information about Java libraries support.
If your "library" project does not change, but you have a jar for it (typically a case of an externally downloaded library), Eclipse allows you to define User Libraries - libraries that can be added to build path of a Java project. To create such a User Library, open Preferences, go to the page Java/*Build Path*/User Libraries, where you can define libraries that consist of one or more jar files.
However, if you are developing your own libraries, and your project does not go into a gigantic size (e.g. several million lines of code), I recommend adding the library project as source into the Eclipse workspace, as in my experience that is easier to maintain in the long run.
First, I would suggest using IntelliJ (in my opinion it's much better than eclipse) but it is very possible to do this and simple as well. So to save time lets pretend all the classes you need in the future library are Network.class, FileUtils.class, and Helper.class. First make a new folder on your desktop called My Libraries. Right click on it and hit Send To, then Compressed Zip Folder.:
Once that's done drag your class files into the folder.
Open up Eclipse and choose a workspace. Once you've done that, you should show up with the default Eclipse screen. Now hit the File tab and hover over New, then go to Java Project.
You will show up with another screen. Enter the name for your project and click Next. Hit the Libraries tab and then click Add External Jars.
Now navigate to your Compressed Zip and click Open.
You now have your library added.
Here is a little ASCII Chart so you can remember:
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Folder -> Class Files -> Compressed Zip -> Eclipse -> New Project -> Next -> Libraries -> Add External Jars -> Compressed Zip (Library)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Dependency bundle (jar-files/sources/API docs) in Eclipse

I'm developing various in-house extensions for JIRA, the issue tracker we use. So far I worked with Netbeans and everything worked like a charm. However, now I need to switch to Eclipse and I'm having struggle setting up the environment for this development project.
First a clarification why I'm using the approach I'm describing here: building JIRA (in an IDE) is not easily done and I'm absolutely not interested in wasting my time to figure out how to do it. Besides, I don't need to build it, I just want to develop extensions and be able to use the IDE's auto-completion and help support (API docs). Atlassian (the company that develops JIRA) provides a "development" package, but it's just a sorry excuse rather than a real solution.
What I did with Netbeans was to create a library bundle with all relevant jar-files, the Java source files and the API documentation. This way I could use auto-completion, "jump to" the source and the API docs would pop-up when needed.
It seems Eclipse doesn't offer such a functionality, at least I couldn't figure out how to add the sources and the API docs to a "User Library" (which I'd then add as a dependency to my project just as with Netbeans).
My next approach was to create a separate project that holds all the stuff and mark that project as a dependency of my project. This works, but it leaves me with another issue: now I get 37k errors reported (all within the "dependency project"). As said, correctly setting up building for this dependency is a major struggle and not my original goal, therefore I'd happily ignore these errors. Automatic building is turned off and changing the "Errors/Warnings" settings under "Java Compiler" for the project didn't change a thing, so I'm kind of lost now.
Okay, let me try to phrase this as questions:
Maybe I just didn't find it: Is there a way to create a dependency bundle (call it whatever you want) in Eclipse that -- besides just carrying jar-files -- gives me the ability to use the API docs and "jump to" the declaration in the sources?
If not, what's the common practice to do in such a situation?
If the "dependency project" solution is the way to go, how can I completely disable compiler errors for that project?
Check this for illustration with images
Add the source code for jar
Add the Javadoc for a jar
Or just right-click on the jar file in the Package Explorer view. Select "Properties" then set the according paths in the "Java Source Attachment" and the "Javadoc Location" field.
When you create user libs via window->preferences->java-build path->user libraries you can specify which jar you need, sources (in archive or folder) && javadoc (from internet, or local, or from archive). Then you can use this lib in your project via context menu on project->Build path->add library->user library-> choose your lib.
Here you acn pick up more info Eclipse help

To check in, or not check in, the entire Eclipse project?

I'm soon going to check in the very first commit of a new Java project. I work with Eclipse Ganymede and a bunch of plug ins are making things a little bit easier.
Previously I've been part of projects where the entire Eclipse project was checked in. It's quite convenient to get the project settings after a check out. However this approach still was not problem free:
I strongly suspect that some Eclipse configuration files would change without user interaction (from when I used Eclipse Europa), making them appear as changed (as they were changed, but not interactively) when it's time to do a commit.
There are settings unique to each development machine as well as settings global for all developers on a project. Keeping these apart was hard.
Sometime if the Eclipse version was different from others Eclipse would get angry and mess up the project configuration. Another case is that it change the format so it gets updated, and if commited messes up the configuration for others.
For this specific project I have another reason not to commit the project files:
There might be developers who prefer NetBeans which will join the project later. However they won't join within the coming months.
How do you organize this? What do you check into versioning control and what do you keep outside? What do you consider best practice in this kind of situation?
At a minimum you should be check-in the .project and .classpath files. If anybody on your team is hard-coding an external JAR location in the .classpath you should put them up against the wall and shoot them. I use Maven to manage my dependencies but if you are not using maven you should create user libraries for your external JARs with with a consistent naming convention.
After that you need to consider things on a plug-in by plug-in basis. For example I work with Spring so I always check-in the .springBeans and likewise for CheckStyle I always check-in the .checkstyle project.
It gets a bit trickier when it comes to the configuration in the .settings folder but I generally check-in the following if I change the default settings for my project and want them shared with the rest of the team:
.settings/org.eclipse.jdt.ui.prefs - it contains the settings for the import ordering
.settings/org.eclipse.jdt.core.prefs - it contains the settings for the compiler version
In general I haven't noticed Ganymede modifying files without me modifying the project preferences.
I recommend to use maven so that the entire life cycle is outside of any IDE. You can easily create an eclipse project with it on the command line and you can use whatever you want, if it's not eclipse. It has it's quirks but takes out a lot of bitterness when it comes to dependencies and build management.
In our world, we check in the entire Eclipse project and the entire parallel but separate Netbeans project. Our motivations for this were entirely focused on "when I do a checkout, I want a functional configuration immediately afterward." This means that we had to do some work:
Create runnable configurations for each primary IDE (people like what they like). This includes main class, working directory, VM parameters, etc.
Create useful start up scripts for all of our relevant scenarios.
Create edited datasets that don't cause the checkout to take too much longer (it's a big project).
This philosophy was worth cash money (or at least labor hours which are almost more valuable) when our new hire was able to check out the project from Subversion into Eclipse and immediately run a functional system with a (small) real data set without any fuss or bother on his part.
Follow up: this philosophy of "make the new guy's life easier" paid off again when he changed IDEs (he decided to try Netbeans after using Eclipse for quite a long time and decided to stick with it for a while). No configuration was required at all, he just opened the Netbeans project in the same directory that Eclipse had been pointing to. Elapsed switchover time: approximately 60 seconds.
I only ever check in things are done by humans, anything else that is generated (whether automaticly or not) should be easy to regenerate again and is liable to change (as you've stated). The only exeption to this is when the generated files are hard (requires alot of human intervention ;) ) to get it right. How ever things like this should really be automated some how.
Try to port your project to a build system like maven. It has everything you need to get the same experience of the project on every machine you use.
There are plugins for just everything. Like the eclipse plugin. You just type "mvn eclipse:eclipse" and the plugin generates your entire ready to work eclipse project.
To give the answer to your question. Never check in files that are not being used by your project at any time in the development cycle. That means that metadata files like eclipse properties etc. should never be checked in in a SCM.
I like checking in the .project, .classpath, and similar files only if they will be identical on any Eclipse user's machine anyway. (People using other IDEs should be able to check out and build your project regardless, but that issue is orthogonal to whether or not to check in Eclipse-only files.)
If different users working on the project will want to make changes or tweaks to their .project or .classpath or other files, I recommend that you do not check them into source control. It will only cause headaches in the long run.
I use IntelliJ, which has XML project files. I don't check those in, because they change frequently and are easy to recreate if I need to.
I don't check in JAR files. I keep those in a separate repository, a la Maven 2.
I don't check in WARs or JARs or javadocs or anything else that can be generated.
I do check in SQL and scripts and Java source and XML config.
I'd suggest having the actual project files ignored by the version control system due to the downsides you mentioned.
If there is enough consistent information in the project settings that there would be benefit from having it accessible, copy it to a location that Eclipse doesn't treat as special, and you'll have it available to work with on checkout (and copy back to where Eclipse will pay attention to it). There is a decent chance that keeping the actual project files separate from the controlled ones will result in loss of synch, so I'd only suggest this if there is clear benefit from having the settings available (or you're confident that you'll be able to keep them synchronised)
In our case, we used to check in the project files (.project and .classpath) to make it easy for all developers to create their project workspace. A common preferences file and team project set were located in source control as well, so creating your workspace was as simple as import preferences and import team project set. This worked very well, but does rely on everyone having a consistent environment, any customizations would have to be applied after the basic workspace is created.
We still do this for the most part, but Maven is now used so of course dependency management is handled via Maven instead. To avoid conflicting information, the .project and .classpath were removed from source control and are now generated via maven goals before we import the team project set. This would easily allow for different environments, as you would simply need scripts to generate the IDE specific portions based on the Maven configuration.
PS-For ease of maintenance though, I prefer having everyone use the same environment. Anything else inevitably becomes a full time maintenance job for someone.
Netbeans 6.5 has an improved Eclipse project import which is supposed to sync changes from Netbeans back to Eclipse: http://wiki.netbeans.org/NewAndNoteWorthyNB65#section-NewAndNoteWorthyNB65-EclipseProjectImportAndSynchronization
Don't. Only check in the source code of your projects.
As a response to:
"There are settings unique to each development machine as well as settings global for all developers on a project. Keeping these apart was hard."
Eclipse offers a number of ways to keep local settings manageable: Java Classpath Variables (Java > Build Path > Classpath Variables) are one, 'Linked Resources' (General > Workspace > Linked Resources) are another http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.user/concepts/concepts-13.htm Creating a README that states which settings to set before building/running the project works pretty well in my opinion.
Now how to make sure your continuous build system understands the changes that were made to the eclipse settings, thats another issue... (I have a separate build.xml for ant that I keep up to date by hand)

Getting Netbeans and Subversion to play together nicely with libraries?

I'm having a difficult time figuring out how to add a .jar/library to a Netbeans project in such a way that I can get it committed to the repository.
The typical way to add a library (per the Netbeans documents I've already gone through) ends up with it just being local to me. Anyone who checks out my project ends up missing my required library.
Inserting it manually and trying to work around Netbeans results in Netbeans hanging while trying to scan the project...
So, how can I tell Netbeans to pick up a jar as a library and include it in my project in such a way that Subversion will be able to handle it?
There are a couple ways to fix this.
A. When you define your Library, use a path to a common location. A location that's identical on everyone's machine--such as the location of a JAR installed with a third-party app into Program Files or /usr/local/ works well or a network drive.
Then, when they check-out the code, the path will still be correct and they do not have to define the Library on their Netbeans workspace.
B. Edit your project.properties file to use a relative path. Open your project.properties file and look for "libs.LIBRARY_NAME.classpath=...". That will be the "default" location used if the Library is not defined.
Change this to use a path relative to your project and store the jar files in your project. For example:
libs.Log4J.classpath=lib/log4j.jar
Keep in mind that the Library definition in your Library Manager will override this value--so make sure you keep them in-sync (i.e. append a version number to the library name!).
C. Use Vincent's suggestion of using a build-system such as Maven. The Maven build-process will take care of downloading dependencies, etc. Netbeans has plugins for several popular build systems.
There is a new feature in NetBeans 6.5 (variable-based paths in projects) which should make this easier.
See http://wiki.netbeans.org/NewAndNoteWorthyNB65#section-NewAndNoteWorthyNB65-VariableBasedPathsInJ2SEJ2EEProjects for details. Note the screenshot includes variable references in the library customizer.
Not really an answer to your question but... generally you should not include these libraries in your subversion repository. There is usually no need to have them managed. What you might want is to set up a central repository similar to what happens with maven. If you use maven, you can create a local repository of libraries on a server accessible by the team. The dependencies on these libraries are entered in the pom.xml file and this is in the subversion repository. Now, as team members check out the code from subversion they all have access to the maven repository.
[I am looking for a reference to this right now. When I find it I'll edit this answer.]
I use NetBeans IDE 6.5.1 and the best solution I've found so far is to include the needed libraries from your local host and then change their paths to relative. After that you have to remove the libraries manually from the NetBeans file explorer, and then copy them from their OS location in your computer manually to the file explorer again. That way NetBeans detects the change and you can commit it to the repository.
Note: I Highly recommend to clean and build the project again after updating.
An easy way to pack up your lib/jars into your project so that subversion "just handles it" so you can grab it out with all the attached libraries ready to compile and go is to include them all under your project directory via the "shared libraries" option by managing the libraries folder.
When creating a new project you can specify "Use Dedicated Folder for Storing Libraries" and then use the suggested relative .\lib path. If you have an existing project, you can edit it's properties, Libraries Category, and Browse for a Libraries Folder. Again a first-time run will suggest .\lib and then offer to copy existing dependencies to that folder. These graphical actions should provide similar results to James Schek's 'B' answer.
Commit the project with the newly added libs in .\lib and you should be able to checkout and build from anywhere and know you'll have the same libs (at the same version) as you had when you last built and committed.
I don't know how long this feature has been in NetBeans. For more details see:
http://netbeans.org/kb/docs/java/project-setup.html#projects-shared-libraries
I ended up just downloading my own set and putting them on my local drive for this project. I setup my Netbeans to look there and warned the other guys what I did... Eventually, we'll have to do something a bit more scalable though... :-)
OK, the working solution that I've now moved to is to extract the class files out of the jars and dump them into the Source Packages area. Then it all gets committed to the repository and also avoids having to deal with handling a separate "lib" directory in the deployment phase.
This solution does everything I'm looking for, yet I feel real dirty about doing it this way. It just seems horribly broken and wrong... :-)

Multi-IDE Support in Java for one Team

What is the best way to allow a team of programmers to use Netbeans, Eclipse and IntelliJ on the same project, thus eliminating the "which IDE is better" question.
Which files should or should not be checked into source code control?
I think the best way is to make the build process independent of IDE. This means that your project should not rely on any IDE-specific files to build, but rather use an external build system, like Apache Maven, Apache Ant, or even make or custom scripts. Maven is supported by most popular Java IDEs, either directly or via plug-ins.
If you don't want to use an external build systems, you should at least make the project as easy to set up as possible (i.e. by having standard folders for shared libraries and other dependencies). When I have working on teams with multiple IDEs in the past, I spent by far the most time on resolving dependencies as the prerequisites for building the project changed over time. In the worst case you may even end up with developers not bothering to get the latest version from the version control repository, since they think setting up the new project is such a hassle.
If your project has many library dependencies, I think its a good idea to make these available in binary form in the version control repository. That way people don't have to resolve all the dependencies of the dependencies and so on just to build a single project. This does however require that you have someone responsible for keeping the "official" binaries up-to-date whenever they change. (This is pretty much the same philosophy used by the Maven repository, but the principles can be applied manually even when not using Maven.)
Well, that's a pretty self-answering question.
The files to not check into source control are files that have to do with the IDEs themselves.
Leave it to the developers to generate these files.
If you use Maven, it can generate the files such as Eclipse's .project and .classpath for you. Eclipse in general is very easy to use with a basic file structure (with the new Java Project option).
I think Maven has Netbeans support as well, not sure about IntelliJ though.
Maven's site is maven.apache.org.
For each IDE that has more than one developer, check-in all the supporting files. Why re-invent the wheel at every desk.
I have done this with many different IDEs, and I have yet to see a filename conflict.
In fact, even when only a single developer uses a particular IDE, it is to his/her advantage to version the supporting files, for the same reason that you version the other files in your development environment: history, diffing, comments, etc.
For Eclipse, that would be .classpath and .project files.
My team uses Maven, and developers are discouraged from checking in Eclipse-specific files. Because they can be generated from Maven, these files are redundant.
Also, checking project-specific files seems like it would save time, but it usually winds up being a pain because of variations in different developers' workstations, resulting in wasted time resolving conflicts in the IDE-specific files. The only way to get around that is to force everyone to set up their environment the same way, which goes against the IDE-agnostic approach.
There are many considerations when using multiple toolsets within the same project team. For example, my team has Java developers using IntelliJ and most of the front end (JSP/CSS/HTML) developers using eclipse. We are in the process of migrating the Eclipse users to IntelliJ because of some IntelliJ plugins that we have developed that provide extended support for our environment. We're not going to develop the plugins for multiple platforms, so we are standardizing on IntelliJ across the board.
In terms of specific files, I can speak to IntelliJ. We have checked in our .ipr files and our .iml files. Do not check in .iws files. If you also have Eclipse users, configure your IntelliJ project to read/store dependency information in the .classpath file and commit that to your VCS.
We intentionally support multiple IDEs from the same SVN repository. Our thinking was that we want to ensure that, if a new person joined the team or someone had to start working on a new machine, we wanted them to be able to checkout the codebase, import it to the IDE and immediately have a work-able configuration.
What that means on the developer end is that they should not commit their changes to the IDE files. Everything else (e.g., src, test, lib and so forth) becomes the set that we normally update and commit every day.
The side benefit is that we have completely eliminated the IDE wars here: Netbeans and Eclipse people live in perfect harmony (looking askance at the IntelliJ people, but hey... ;-).
For more comments and answers on this topic see this question (How do you handle different Java IDEs and svn?)
We rename our IDE files for checkin with an extra extension .deletethis or similar. When a new person checks out the project, they simply strip off the extra extension and are good to go. This way we avoid source control conflicts with the project files as people tweak their environments. And you don't have to worry about educating new developers to not check in those files.
Typically, I would consider this a bad idea. I'm not sure what kind of environment this is (perhaps open source?), but it would really suck to support multiple IDEs. One thing I would recomend if this is unavoidable, would be to standardize your builds in ant scripts. If you have a large set of dependencies, this may be the easiest way to get a predictable build across all platforms.
If one of the IDEs happens to be RAD (based on eclipse), there is an entire folder called .settings that you would not want to include in the SCM.

Categories