Eclipse(STS)/Maven integration issues - java

I am working on a fairly big project that uses maven for dependency management. As part of this we are using Maven profiles to build and replace certain properties files that differ between test/dev/production environments.
To perform a build I would execute a Maven:build using the correct profile and mavens reactor would then build the projects in the correct order and store the jars in the .m2 folder, eg the domain jar first, then the service jar (with the domain jar included in its jar as a dependency) etc. This leads to a war file eventually with all the correct libs required by the war to run.
When eclipse performs its default build that it performs everytime you save a file the jars are not built with any profile, just a regular build.
When I then push the final war file to the server and it is exploded when the server starts up (started and deployed through eclipse) I get in the lib folder all the jars that maven had packaged into the war file but also all the jars that eclipse had built.
eg
lib/
domain.jar (built by eclipse)
domain.SNAPSHOT.1.0.jar (built by maven)
etc
Is there any way to prevent this from happening? This has the end consequence of there being two of every property file and only the order in which they are loaded determines which is used. A real hassle as different properties are used in different environments.

I found a slightly hacky solution to this problem.
In the web projects properties -> Deployment Assembly I modified the path for the offending jar files eg domain.jar from
WEB-INF/lib/domain.jar
to
WEB-INF/autogen/domain.jar
This leads to the eclipse generated jar files (with the wrong properties files) to be deployed to a folder that won't be loaded when tomcat starts. Not a perfect solution but it allows all the nice things of eclipse auto-building like code completion and error messages in the web project if the interface of the domain changes etc while also providing the correct profile when deployed.
Leaving this here for anyone else in this situation.

Related

Eclipse build automatically to do maven build?

I have my main web application(has its own POM) that is dependent on module A((has its own POM).
When i make a build using mvn install on web application, it dependent modules
are also built in to jar file and ultimately included under WEB-INF/lib folder of main web app.
But that does not happen in when i make build using eclipse kepler (containing both maven projects i.e main web app and its dependent module A).
When building with eclipse, it just put the modified classes under moduleA/target/classes/ folder but does not make any updated jar file and put it
under WEB-INF/lib folder of main web app.
Is there a setting where i can configure eclipse building the project same way as maven does (which will really save lot of time and help in hot deployment) ?.
It used to work in one of my projects looks like some configuration is required for this.
looks like m2e connector(i have SonarQube) needs some configuration to make eclipse build in the same fashion as maven build
When i do the project > right click > mvn install , i am able to make jar file.
But what i want is eclipse build automatically option do
the build for project/module wherever modification is done , construct the jar and include it in parent WEB-INF/lib folder if it is dependent module ?
Assuming you're using the Java EE flavour of Eclipse, you can easily deploy Maven based web applications to a local server (like Tomcat, Wildfly...) from the server view.
m2e-wtp, included in recent Eclipse Java EE distros, takes care of configuring all Eclipse settings based on your project pom.xml configuration and dependencies.
See this screencast to see how simple it is : https://www.youtube.com/watch?v=TksoKkSP208
For the record, deployment/publishing is performed by each server adapter differently. They're responsible for publishing the proper jars under the WEB-INF/lib folder of the deployed application. Dependent jar projects are automatically zipped and deployed to WEB-INF/lib without user interaction

How is in the real world deployed Maven application?

I have a Java console application, till now it was developed in Netbeans IDE. When Netbeans builds application, it creates dist directory and builds an app into this directory as a jar archive and into dist/lib copies all dependencies. This this directory could be copied into final destination and run.
Now I'm trying to transfer this project into Maven. Everything goes ok, I can compile and package my app and a jar is created into target directory. I use maven-jar-plugin to set main class in manifest and maven-shade-plugin to package all sources into one jar file.
I would like to ask you how is such Maven project deployed in the real world? Should I use all target directory, copy it ad the final destination and run as I have been used to do with Netbeans? What are consequences when I don't use maven-shade-plugin - where are all libraries defined as dependencies located? I am asking, because in my testing project these libraries don't exist in target directory.
My question - I have a Java console application "A" packaged via Maven (without maven-shade-plugin) and Linux server "S" where this application should run. Can I copy all target directory manually to server "S" or is there some better / more automatic way how is this solved in the real world?
Simply copying over the target directory will not solve your problem. I have packaged many standalone applications using Maven and I have used Maven Assembly Plugin for it. You can create a distribution archive (zip, tar.gz) using the assembly plugin which your customer can unzip and start running.
It depends on you, how you want your target application directory structure (release). I usually end up with something like
bin/
conf/
lib/
log/
The bin directory contains a shell / batch script to run your program by calling your main class, setting appropriate classpath, providing relevant memory settings etc. I prefer using classworlds (which is used by Maven) to bootstrap my application and simplify writing of start scripts.
conf directory contains configuration files for your application as well as logging configuration files like log4j etc. This directory I add on classpath to make it easier to access configuration resources at runtime.
lib directory contains all the dependency jars a well as jar file for your code.
log is where your logging configuration will point to output log files.
Note that this structure is good for standalone server like applications. Also having a bin directory and run scripts allows you to add this directory to PATH on Windows / Linux to ensure you can run the application from anywhere.
If you are packaging a command line utility, simple shaded jar may work for you. Personally, I am not the biggest fan of java -jar application.jar
The question is too broad to be answered comprehensively, but I would like to provide an example of real-world maven deployment.
There are maven plugins for all major application servers. They have defined targets for local and remote deployment. One such plugin is the jboss-as-maven plugin. You can define the deployment properties (IP, port etc.) in your .pom or directly from command line, e.g.
mvn jboss-as:deploy -Dpassword=mypassword
There is also the cargo plugin that specializes in application deployment.

Deploy Maven artifacts to <container>/shared/lib for Eclipse debugging?

I'm working with some very old, monolithic software that is basically a heavily customized JBoss deployment. Unfortunately, this means that JBoss can't be started from the "Servers" view in Eclipse, it must be started as a Windows service or via the command line. There are multiple WARs/EARs, but the WAR classloaders are rarely used and most of the actual class files are located in jboss/shared/lib as .jars.
We need a way to run a Maven build in Eclipse (via m2e) and deploy the class files in the resulting .jar to C:/product/jboss/shared/lib so that when we start JBoss, we can use Eclipse to debug (as a remote java application). Ideally, the artifact that Maven pushes will not overwrite the existing .jar file that was originally installed. For example, if the Maven project builds an artifact named myjar-1.0.0.jar, we need a way to deploy the classes inside of myjar-1.0.0.jar to C:/product/jboss/shared/lib/classes so that they are picked up by the classloader prior to C:/product/jboss/shared/lib/myjar-1.0.0.jar, which was installed with the product.
Currently, our (very hacky) solution is this:
Under the project configuration's Java Build Path > Source tab, we use the "symlink" functionality under Advanced to map the Default Output Directory (e.g. project/target/classes) to a class folder (e.g. C:/product/jboss/shared/lib/classFolder). This modifies the .project file, which is checked into source control.
We build the project normally with a m2e launcher (e.g. clean install).
Assuming the Maven build is successful, we run an Eclipse project build. This pushes the class files to C:/product/jboss/shared/lib/classFolder:
We restart JBoss. Since classFolders take precedence over jars, JBoss will load the classes in C:/product/jboss/shared/lib/classFolder, which are identical to the classes in our Eclipse workspace.
We attach to JBoss and debug the project as a remote java application.
Pros:
We're able to push our new classes to JBoss and test them without backing up the original jars and copy/pasting the new ones by hand (jar hell).
Cons:
We're compiling twice -- once with the maven-compiler-plugin, and
once with an Eclipse project build (Java Builder).
The symlink functionality is hit or miss in my experience. Sometimes we need to
do the refresh project/close project/build project dance to get it to
work.
Is there a better way to do this? I cannot force them to restructure the project so heavily that all deployables are container-agnostic WARs, but our developers need to be able to make changes and quickly test them without manually copy/pasting .jars.
How old is old?
Have you looked at the Cargo plugin?
http://cargo.codehaus.org/Quick+start
It can deploy to JBoss 3.x.
It has a Java API so you should be able to write something to extend it to do what you want.
Why are you trying to deploying classes instead of jar files?
You can still remote debug via Eclipse with jar files.
Worst case scenario - use Ant.
Maven is not designed for this kind of stuff, trying to force it to work will just cause you pain.
Once you have got Maven generated the right artifacts, work out what you would do manually and then script it via Ant.
I would try looking at the maven-dependency-plugin which has the possibility of copying artifacts to different location.
Please check your Deployment Assembly (project -> properties -> Deployment Assembly) and verify if your maven libs are there.

Automating build process for a web application created in Eclipse

I have an eclipse Tomcat project that has several dependencies on other eclipse projects.
For example imagine the main project is called server and has several dependencies:
server
(depends on):
data-lib
server-utils
messaging-utils
Currently every time I change data-lib,server-utils,messaging-utils I have to recreate the .jar file and copy it into WEB-INF/lib directory of server. At that point I export the server as a .war and deploy to my server.
I want to make this process work from the cmd line using ant (note I know maven is out there but I know ant pretty well from past experience so would prefer sticking to it for now). Its easy enough to create the build file for server -- it will end up creating a .war file. But I want it to automatically build the dependent libs. I want to do this while preserving my development workspace in Eclipse.
What is the easiest and cleanest way to do this? Currently my thought is each individual project will have its own build.xml (i.e. data-lib/build.xml , server-utils/build.xml , etc). I will have the server/build.xml do an antcall to these individual build files and then copy the jars to the server/WEB-INF/lib directory.
Is there an easier/better way?
if you want an Ant based script, I would go with Apache Ivy. The basic idea is that each of your submodule has its own build.xml file and publishes (via Ivy) their "publications" (like a Jar file) to a repository on the file system. The other modules then import these "publications" to build the final product.
I am not sure if it can help you, but in your WAR project, right-click on it in Package Explorer, and click on Properties.
There is a "J2EE Module Dependencies". In this option, select all of the dependencies (i.e. "data-lib", "server-utils" and "messaging-utils").
Now, when you modify a Java class in one of the dependencies, Eclipse will recreate the JAR file and deploy it directly in the WEB-INF/lib of your web application.

Eclipse debug-time classpath problem: How do you include a dependent project's output into a web project's runtime classpath?

So I started with a web services project (just a dynamic web project) that builds and debugs correctly from eclipse. We've pulled a chunk of common code out that we want to put into a shared library so now those classes are going into a separate jar project that the web project references.
On the web project, I did Project->Properties->Java Build Path->Projects->Add and added the jar project. And this correctly solved all the compile-time classpath problems and everything builds fine. But at runtime, when the tomcat server fires up, spring attempts to inject some of the classes contained in the jar file and I get a NoClassDefFoundError.
My .class and properties files and the contents of my META-INF directory are showing up in the ./build directory, but my WEB-INF/lib directory seems to be referenced in-place, and the jar dependency doesn't get copied in to it to show up as part of the Web App Library.
What is the magical incantation to tell eclipse that the other jar project needs to be available to tomcat at runtime? From our ant build script, we first just build the other project into WEB-INF/lib and everything works fine, but not for eclipse debugging.
I figured this out after spending some time on it. If you are in Eclipse Helios , go to properties > deployment assembly > add > project and select the dependent project you wish to add.
Java EE module dependencies would solve this problem.
You have already done the task of extracting your common classes into its own project, possibly because other projects depend on these classes. Either way, you'll have to ensure that this is a Utility project (appears under Java EE in the project wizards), and not just a plain Java project.
One that is done, you can proceed to add the Utility project to your build path (compile-time path) as you have figured out.
The additional (final) step is to establish a Java EE module dependency between your Dynamic Web project and the shared library, which causes the utility's classes to be placed in WEB-INF\lib during deployment, and even during export of the WAR. To do so, visit the dynamic web project's properties, and browse to the Java EE module dependencies. Ensure that your utility project is selected here. Redeploy/publish your application and you should be good to go.

Categories

Resources