Add external jar to web project class-path - java

I have a web application developed in JAVA and I have a jar file. I would like to add the jar file to the application class-path. I know a web application includes libraries from WEB-INF/lib/* but I want to include a jar under this location C:/myLib.jar. Is that possible, if it does how can I do it?
regards,
micuss

ok, jboss is a bit difficult on classloading, but its definitely possible.
you need to add a new jboss module for your external jar and then declare your web application to depend on that module.
there's a complete guide for this here.
its possible to define a module to reference a jar file completely outside the jboss folder (c:\mylib.jar in your case) but it'll be easier on you if youre willing to move the jar into /modules
see here for complete documentation on how to write module descriptors. you can set the path to lead to your external jar (but its gonna be ugly)

Related

Tomcat: Load Classes Copied into WEB-INF/lib at Web App Startup?

My organization is creating a "base" Java web app that is meant to be customized by adding jar files (with customized classes) by adding the jar files to the web app's WEB-INF/lib directory. The goal is that our developers can simply create custom code, packaged as a simple jar file, which can be loaded into this "base" web app, so the developer doesn't have to worry about all the web app plumbing, just the actual custom code.
We're investigating a few different deployment models, but one idea was to put these jar files somewhere on a network directory. When the Java web app starts up, a ServletContextListener copies these jar files into the web app's WEB-INF/lib directory (the web app is originally deployed as a war file).
Then, another ServletContextListener uses Stripes' ResolverUtil class (JavaDoc here) to load all of the classes of a particular type (in this case, that implement a particular interface) that are located in the jar files that were copied into WEB-INF/lib.
Unfortunately, ResolverUtil fails to find those classes, even though they are in those copied jars. If I restart Tomcat (with those jar files still in WEB-INF/lib) they are found, as expected.
The jar files need to be in WEB-INF/lib because we want to use the Servlet 3.0 feature in which JSPs can be served from jar files, and for that to work, apparently those jar files need to be in WEB-INF/lib. If that weren't the case we would just add those jar files in the shared.loader property in catalina.properties.
So, it appears that Tomcat has already scanned the classpath for all class definitions by the time a web app is started, and since those jar files weren't in WEB-INF/lib when the web app started up, the classes will not be found.
Is there a way for those classes to be found? I don't need Tomcat to completely reload itself; I just need those new jar files and the class files they contain to be visible to the class loader. Is there a way to tell the classloader, "Hey, check the classpath again for new jars!" as I would only need to do it once, when the web app starts up?
Any other ideas?
Thank you!!

Make WAR executable like JAR to provide command line interface out of the application (JBoss)

I have a servlet which have some logic and is used via browser like every servlet. Now I am looking for method to do the same thing what servlet does, but it should work like CLI. CLI sends requests to logic deployed on JBoss (classes in war file) and print responses on terminal (command line). It should trigger the same logic and all things should be placed in this one war file.
So let's say I will write java code which provides this funcionality. It should be compiled to jar and placed in war, then this jar should be launched from war. It doesn't have to be a servlet. Only requirement is taht everything should be in this one war file. CLI should be called via one line, something like java -cp jarfileinwar com.blah.Main.
Logic should work on JBoss JVM where everything is deployed, it should work like servlet, but method of call should be CLI.
Greets
An executable jar file has a different structure from what a war file has, so I don't think that you're going to be successful in trying to create an executable war file.
You can, however, repackage your required classes and the classes from your jar dependencies into one big "uber jar", and then make that executable by means of the propert manifest entries.
Doing this is not straightforward by hand, so I'd suggest using a build tool to accomplish this. Maven has two plugins - the Shade plugin and the newer (I think) Maven Assembly plugin that can do this quite easily.
A benefit of using Maven is that you could have two different targets - one to build the war file, and one to build the executable jar file, from the same project.
I couldn't stop thinking about it. As I've commented the original post, I thought it is possible to make WAR files executable by imitating an executable JAR within a WAR.
On top of a Maven 3 web project arche type (as foundation) I've created a little proof of concept project that actually implements this.
Take a look:
https://github.com/is-already-taken/executable-war-example
It uses a custom classloader (this article about classloaders from javablogging.com helped me dong this), a "bootstrap" class that loads the first portion of business logic using our custom class loader and a custom Manifest. The classloader is used to "intercept" the class loading to search classes at the location where classes usually are located in a WAR file and to extract classes from libraries packaged within WAR files using streamed unzip code.
Maybe there's still such a out-of-box solution or something that comes with a Maven plugin, but I didn't found it. Further, this small proof of concept helped me leanring class cloader stuff aswell. ;)
I'm looking forward to comments on my solution and my approach in general.

How can I define a different target folder for some dependencies in Maven

I run many instances of the same web application under Tomcat and to save memory I copy some of the libraries to Tomcat's lib (tomcat\lib) and shared (tomcat\shared) folders. Libraries that go under lib can be found by both Tomcat and web applications, libraries that go under the shared-folder can only be used by web applications. My web application also need some libraries on the web application level so those libraries goes under WEB-INF\lib.
I have defined in my pom.xml that most libraries have a scope of provided so that they're not copied to WEB-INF\lib, however is there any way to define that I would like some libraries to go under a custom-defined folder; e.g. WEB-INF\lib\tomcat\shared and WEB-INF\lib\tomcat\lib, from where I could mover them manually to Tomcat's corresponding folders on the server?
That is not really the recommended way to package dependencies, as usually the web application would be deployed without furhter modification of the war file.
I think you can archieve what you want using the dependency:copy-dependencies goal, but it would require some configuration. You would have to set includeScope to provided, set the correct outputDirectory and then define the artifacts with the includeGroupIds or includeArtifactIds options.
Make a separate maven project which contains the war file and define the dependencies which should be located in the share-folder as scope: provided. Furthermore create an other separate module which has these dependencies and create an appropriate archive from it via maven-assembly-plugin...

How do I include external JARs in my own Project JAR

I have a Java application and created a JAR file and deployed it.
The App uses external JARs such as the Log4J JAR. When creating my JAR file, how do I include all external dependent JARs into my archive?
In order to get my App working, I'm having to copy the Log4J JAR into the same directory as my own JAR which kinda defeats the purpose of the jar. Wouldn't it be more elegant to have 1 single JAR file to deploy?
If you use Eclipse, You can extract all included files into one runnable jar like this:
Right click on your project name from Package Explorer and select Export.
In Export screen, select Java -> Runnable JAR file and Next.
Fill in the Runnable JAR File Spec screen and Finish.
You can choose whether to package dependency jars as individual jar files or extract them into the generated JAR.
You could use something like One-JAR to package your Java application together with its dependency into a single executable Jar file (One-JAR uses a custom classloader to make JARs nesting possible).
You have to expand the library jars into the same place where your compiled classes go, then make a jar from that. Depending on how your build process is set up, there may be multiple ways to achieve this. It's not rocket science - a jar is just a zip archive with a META-INF directory at the root level.
Keeping JAR separate is better as it is easy to upgrade only the specific JARs to its new versions without touching any other configuration. As of your issue of having to copy each file to same location as of your JAR, you can always use Java CLASSPATH and include any JAR to your application's class path.
A JAR is not itself capable of nesting other JARs, as you discovered.
Traditionally, one would distribute a ZIP archive or other installer that would unwind the application JAR (yours) as well as any support JARs in the appropriate location for classpath access. Frequently, then, the application was invoked through a script that invoked the primary JAR and created a classpath that listed the support JARs.
As other posters have noted, you have some options to create a super-JAR if that's what you want.
You can use Maven + assembly plugin (http://maven.apache.org/plugins/maven-assembly-plugin/)
BTW, probably that's not the easiest way, if you did not work with maven.

Java Web Project referencing another Java project

I have a Java Project, for which I'm now creating a Web interface, using a Dynamic Web Project from Eclipse. The Web project consists of a single servlet and two JSP's. Something like this:
/JavaApplication
/src
/lib
/resources
/WebApplication
/src
/Servlet.java
/WebContent
/WEB-INF
index.jsp
other.jsp
Now, I need to reference JavaApplication from WebApplication, in order to use its classes to process web requests. What's the best way to accomplish this ? My idea is to create a .jar of the JavaApplication, containing all the .class files, /resources, and /libs. In this way, I could include the .jar in the web application, and I could have a single .war file that contained the entire application.
What do you think? How is this problem typically solved ?
Note: I don't want to convert the Java Project into a Web project.
In Eclipse project properties, add the project to the Java EE Module Dependencies (Eclipse 3.5 or older)
or Deployment Assembly (Eclipse 3.6 or newer) entry in the project properties.
This way Eclipse will take care about doing the right thing to create a WAR out of this all (it will end in /WEB-INF/lib). No other configuration is necessary, even not some fiddling in Build Path.
Under Eclipse, you can declare Project References for a given project, the web application in your case. To do so, right click on your web application project, then go for Properties > Project References and select the JavaApplication project. This should allow you to call code from the JavaApplication project from the WebApplication without having to build a WAR. This is a solution for development.
For standard deployment (outside the IDE), you should indeed create a standard WAR. To do so, you'll have to package your JavaApplication as a JAR including the .class files and the files under /resources but not the libraries it depends on (JARs under /lib). These dependencies will actually end up in the WEB-INF/lib directory of the WAR, beside the JAR of your JavaApplication. These steps are typically automated with tools like Ant or Maven.
Connecting java app to web app for development :
right click on web project :
properties>project references> add the java project you want to refer
Now in properties tab of web project go to
properties>deployment assembly> add the project manually and run the app
Consider moving up to EAR level, if your web container supports that.
The tricky part with shared code is where should the common code be put. A copy pr web application? A copy in the web container? Overdoing the "share these classes" might end up in class loader problems.
If you are creating two separate web applications refactor common java code into a separate Eclipse project and refer to it from both WAR projects.
EDIT: Apparently I have misread the problem description, and thought you asked about an existing and a new web application sharing code.
If you have an Eclipse project with your application, and another with your web frontend, then you can let your application export the necessary resources which the "Export WAR" in Eclipse Java EE can wrap up in a jar file and put in WEB-INF/lib for you. You need to say this explicitly with a checkmark in Properties -> Java EE Module Dependencies for your web project. Expect you have to experiment a bit - this took me a while to learn.
Typically you would create an API interface using remote service beans from the Java application that expose the methods that you want to invoke in the web application. You would include a proxy of the API interface with your web application that calls the remote service bean in the Java application. Remember that you will need to register the remote bean in the web.xml file.

Categories

Resources