Deploy two WARs with IntelliJ idea to tomcat - gradle

We have recently migrated from maven to gradle and since the migration we are experiencing following issue with deployment.
Our war-related part of gradle.kts looks as follows:
tasks.war {}
// Register named war for local development so IntelliJ Idea correctly creates deployable artifacts.
tasks.register<War>(project.name)
We can easily deploy created artifacts and access their endpoints on their host:port.
However, once we deploy secondary artifact (on different port), suddenly the first deployed service fails with following error:
java.nio.file.NoSuchFileException: /usr/local/Cellar/tomcat/9.0.38/libexec/webapps/ROOT/WEB-INF/lib/netty-buffer-4.1.32.Final.jar
The full stack trace is here: https://gist.github.com/knyttl/25711ccd79556f346e605bb652606cfd
I guess there is some misconfiguration, but I haven't found anything related to it.
Only difference from Maven is that now we are using the "non-exploded" artifacts as I didn't manage to build them properly with gradle.

The whole issue seems to be caused by the usage of non-exploded WAR.
Solved with using exploded WARs as described in https://stackoverflow.com/a/49523230/922584.

Related

Injection Dependy of a Multimodule Maven project in Maven

I have the following issue.
On one hand I have a multi module maven project, which I use maven install to write the .jar files in my local .m2 repository. This is working fine. Lets call it MultiA.
Now on the other hand, I have a spring boot project (lets call it SpringB) in which I bind the .jar files from my multi module maven project. This is working fine as well. When I execute my buisness logic from IntelliJ, I receive no issue, but when I build the project as a .jar, I receive an issue because the settings.properties file from MultiA are not found. I do not try to access settings.properties from SpringB, but I call a method from MultiA, which in return trys to access the settings properties.
I hope, this description helps and someone knows the answer to this problem.

WebSphere 7 org.apache.axis2.deployment.WarBasedAxisConfigurator <init> org.apache.commons.fileupload.FileUploadException

This is a strange problem. I have an existing JEE project that is and has been in production on WebSphere 7. It is a multi-module EAR file. It has 2 WARs and 1 shared Java project. Most of it is Spring 4 based, but we have some web services we host using axis2 (1.5.4). This project does not use Maven. It does use a WebSphere deployment.xml (in the EAR) with the warClassloaderPolicy="SINGLE" and the classloader mode="PARENT_LAST". This controls the classloader policies for this EAR. All the jar files that the Java project and the WARs rely on are stored at the EAR level and referenced at the module level via the manifest files. That all works fine and has for several years.
Now I was trying to convert this project to a Maven project after all these years. Initially, I left the deployment.xml file settings as they always have been. But with these settings I was getting:
java.lang.VerifyError at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl "org.springframework.oxm.jaxb.Jaxb2Marshaller".
After much googling on this site and all around and trying 50,000 things, I tried one thing, which worked for most of the app. I switched the classloader mode to "PARENT_FIRST" and all of a sudden the WAR that exclusively uses Spring 4 worked. It started up without error and I was able to run it.
But, the other WAR which hosts the axis2 web services started getting the error:
org.apache.axis2.deployment.WarBasedAxisConfigurator <init> org.apache.commons.fileupload.FileUploadException....Caused by: java.lang.NoClassDefFoundError: org.apache.commons.fileupload.FileUploadException....Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileUploadException
This class (org.apache.commons.fileupload.FileUploadException) is in both the compile and runtime classpath. In eclipse I can see it in the "Maven Dependencies" library that the m2e eclipse plugin creates from the POM files. I can also see this jar in the WebSphere runtime module classpath inspector (it shows up in there 3 times! Once under each WAR and once just in a list from the Maven repository location.)
One thing of note is that I've configured the project with a parent POM, where most of the dependencies are declared at the parent and then are inherited for each of the modules. In the EAR project, the POM is using the maven-ear-plugin with skinnyWars=true. However, it appears the skinnyWars directive is not respected when the m2e eclipse plugin deploys the EAR into the local WebSphere server (that is evident because I see these jars showing up in the classpath 3 times). But when I create an EAR using the Maven build, the EAR comes out correctly with each jar only showing up in the EAR one time.
This is my last hope to post something here and see if someone has an idea for something to try, otherwise I can't think of anything else to try.
Thanks...
Is there a particular reason you need to run with a single class loader for all the WAR modules, other than convenience? If not, you could rework the application in order to allow you to run PARENT_FIRST in the Spring WAR and PARENT_LAST in the Axis2 WAR.
If that's not an option for some reason, the path of least resistance might be to go back to PARENT_LAST and remove some libraries from the app or module. The VerifyError generally occurs if you're running with PARENT_LAST and have a library in the app that is also present in the server - in this case, the exception looks like it's coming out of JAXB, so you might want to see if simply removing JAXB (and perhaps JAXP, if present, since it's heavily used by JAXB) from the application resolves the issue with your default setup.
You could also stick with PARENT_FIRST and move the Axis2 jars to an shared library with an isolated class loader, associated with the app. An isolated shared library would make just the stuff in the shared library PARENT_LAST, so you can avoid the VerifyError and still get PARENT_LAST for Axis2. The issue in the PARENT_FIRST case appears to be because you're picking up WebSphere's copy of Axis2 but somehow have a dependency inserted from your app's copy - the failing class load is occurring in a server-level loader, so it doesn't see the copy in your app.

Spring Boot Run Configuration Issues

I am trying to run my spring boot application (via Run As -> Spring Boot Application) in a tomcat8 container on STS and I am receiving these errors:
Caused by: java.lang.IllegalStateException: Expected method not found: java.lang.NoSuchMethodException: org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.addApplicationListener(org.apache.catalina.deploy.ApplicationListener)
at org.springframework.util.ClassUtils.getMethod(ClassUtils.java:627)
at org.springframework.boot.autoconfigure.websocket.TomcatWebSocketContainerCustomizer.addListener(TomcatWebSocketContainerCustomizer.java:85)
at org.springframework.boot.autoconfigure.websocket.TomcatWebSocketContainerCustomizer.access$100(TomcatWebSocketContainerCustomizer.java:36)
at org.springframework.boot.autoconfigure.websocket.TomcatWebSocketContainerCustomizer$1.customize(TomcatWebSocketContainerCustomizer.java:50)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.configureContext(TomcatEmbeddedServletContainerFactory.java:355)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.prepareContext(TomcatEmbeddedServletContainerFactory.java:184)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:154)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:157)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
... 7 more
I have searched around for this quite a bit and have found little to guide me in figuring out what the problem is. After going through the spring boot code in the debugger I see that the object named "instance" referenced in the TomcatWebSocketContainerCustomizer.addListener() uses reflection to retrieve a handle to it. This object is associated with the tomcat 7.0.53 jar ($HOME/.m2/repository/org/apache/tomcat/tomcat-catalina/7.0.53/tomcat-catalina-7.0.53.jar). I do not see this in any of my maven dependencies and have tried several techniques to force it to tomcat 8.0.20, nothing seems to work.
After banging my head for a while I started looking at the run configuration for the project in STS (via Run As -> Run Configurations). I found that the Source tab shows tomcat 7.0.53 above version 8.0.20 along with several dependencies that aren't referenced in maven. I am at a loss on where these values come from and not sure how to edit it. For some reason when I try to manually delete these legacy jar files STS doesn't allow me to delete any of them.
Does anyone have an idea of where these dependencies may be coming from and how I can remove them?
They do reference my $HOME/.m2/path/to/tomcat-catalina/<version> dir, so I could simply remove them from my .m2 and theoretically it may work but I'd rather not do this if I don't have to.
I am using spring boot 1.2.x and all of them have this problem.
thanks.
I've got two ideas that you might try.
1) It is possible, that this may be manifestation of this bug in STS 3.6.4: https://issuetracker.springsource.com/browse/STS-4085
The depencies you aren't expecting to see may be coming from the maven 'test' scope. (The bug explicitly mentions 'srt/test' but the same happens with jar dependencies). You can verify whether this bug is the cause by using the regular "Run As Java Application" on your main class.
If that works, then it is almost certainly this bug. If it also fails with a similar error then its something else... then try:
2) You must be getting the unwanted tomcat version from somewhere, probably indirectly as dependency of something else.
Try using the m2e 'dependency hierarchy' to find where it came from like so:
open pom.xml
Click the 'Dependency Hierarchy' tab.
Type 'tomcat' in the 'Filter' box.
I finally figured it out.
In my $WORKSPACE/.metadata/.plugins/org.eclipse.m2e.core/workspacestate.properties it lists all poms, jars and wars from my workspace build with the maven plugin. I noticed that a pom in the file points to the exact version tomcat that is being loaded in my spring boot project. Once I deleted these projects from my STS I can successfully launch the spring boot app :-)
When I re-import the maven projects back to STS the error occurs again, then disappears when I remove them.
These projects have no connection to the project that I am trying to launch. Therefore I think the bug is in m2e.
I'll file a bug and update this post when it is complete.
thanks #Kris for working through it with me.

how to build separate war files for glassfish and tomcat using maven3 ?

I have a Java Web project built by Maven 3.
The requirement is to have its artifact run in multiple container types (e.g. Tomcat6, Tomcat7, Jetty8, Glassfish4, WebSphere...)
The issue is that different containers have different dependency requirements. For example, Glassfish4 does not support deploying a WAR with Jersey JARs inside, while Tomcat7 requires these JARs.
Hence I need some mechanism to define several WAR artifacts, each one with different dependencies tree. Profiles might be one way to go, but that would require several build executions, one for each type of target container.
Is it possible to have one build execution produce several WARs, each WAR having different dependencies trees?
What you want is the profiles feature.
You have a profile for each of the app servers and enable only one, and run the goal, then do the next one.
There is very comprehensive documentation on profiles on the maven site.

How to use Maven to download from Nexus for a deployment

I am somewhat new to Maven but we are successfully using Bamboo to deploy to Tomcat using Maven and Tomcat7 plugin. However I want a separate Bamboo build plan that only deploys a war package from Nexus, does not re-build it first. Looks like I could make the war a dependency but this same POM builds the package, so I don't want it downloaded in the case that a build goal is called.
Look at the maven-dependency-plugin. It should be easy to have a project grab an existing war artifact and push it to tomcat.
Nexus has a very rich REST API that you could easily use to script the deployment with a simple http get and a copy. However if you really feel like you want to use Maven ptyx approach should work ... although it seems like overkill. If you invest into effort for deployment I would look into using Chef or Puppet instead and use them to pull from Nexus and push into your production (or QA or whatever servers).

Resources