To summarize the issue I'm encountering, I have an EJB which uses version A of a library (let's call it dep-vA.jar). dep-vA.jar is packaged in the root of the EJB's jar file. The domain lib folder in the application server contains version B of the same library (let's call it dep-vB.jar). When calling the EJB, I get an error due to dep-vB.jar file being loaded rather than dep-vA.jar.
I guess the first part of this question is, does Sun One Application Server v9.1 isolate EJBs from each other? I was under the impression that it does. But it seems like another application loaded dep-vB.jar and this EJB is directly using it without loading its own.
The second question is, if the app server does isolate EJBs, does it load dependencies from the EJB's jar file before looking in the application server's lib folders? I was under the impression that this is also true, but maybe not...
Is anyone familiar enough with Sun application servers to explain why dep-vB.jar is being loaded rather than dep-vA.jar? Is there any way to get it to load dep-vA.jar without changing what's in the application server's lib folders? (I would hesitate to do anything that might affect other applications on the server)
Thanks.
I guess the first part of this question is, does Sun One Application Server v9.1 isolate EJBs from each other? I was under the impression that it does. But it seems like another application loaded dep-vB.jar and this EJB is directly using it without loading its own.
According to Sahoo (which is a GlassFish developer), the Java EE spec does not mandate class loading isolation among modules of a single ear so the behavior can be different from one app server to another. With Sun ONE, my understanding of the documentation is that EJB-JARs are isolated.
The second question is, if the app server does isolate EJBs, does it load dependencies from the EJB's jar file before looking in the application server's lib folders? I was under the impression that this is also true, but maybe not...
It's a parent-first strategy (and to my knowledge, Sun ONE allows to change the delegating mode for webapps only).
That being said, what happens if you list dep-vA.jar in the Class-Path entry of the MANIFEST.MF of the EJB-JAR?
See also
Chapter 2 Class Loaders of the Sun Java System Application Server Platform Edition 9 Developer's Guide
Packaging EJB 3 Applications
I haven't used that particular server, but I do know that in WebSphere, there is an option to use PARENT_FIRST or PARENT_LAST classloading. You would be looking for an equivalent of PARENT_LAST where the classes are loaded from the EAR first before going up to the server.
I would assume that such a configuration is possible in any app server, as you should always be able to enforce your application specific jars to be loaded over any others.
Related
I want to shared common application context in a multi-war Spring application, so i don't need to defined beans again and again. But i don't want to instantiate those beans defined in this common application context in each webapp. I only want to instantiate those beans once and share by all the webapps. Is it possible? Bare me if i'm wrong.
PS: this common application context exists in jar, which i'll import to every webapps.
1, Below article tell us how to share the common application context, but need to instantiate those beans in each webapp.
How to import spring-config.xml of one project into spring-config.xml of another project?
2, Below is another article i just read, i demo it, but still don't get what i want, beans got instantiated twice. Can someone check this section "Why would you want to use this?" in the article, i don't get it, do they have a solution there, can someone help me here, thanks a lot for your time.
http://spring.io/blog/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/
here is the demo source code in second article: https://github.com/jasonluo/ceciic/tree/master/Research/multiple-contexts-sample
Updates
The problem of case2 is because i didn't deploy as a ear file, thanks Deinum for pointing this out, i'm using tomcat, so there is no way to achieve that.
Our solution now is using REST to access the service webapp which running in a separate server.
Don't, there is usually classloader isolation going on to prevent this. Doing this right usually requires a thorough understanding of classloading, Java EE, packaging and your server.
Having that said there is way to do this as outlined in the blog you posted. You have to:
package both WARs into an EAR (this means you have to use and appserver like WildFly AS and can't just use a servlet engine like Tomcat or Jetty)
package both WARs as "skinny" WARs with at least Spring (and all its dependencies) and the shared beans (and all their dependencies) in the lib/ folder of the EAR instead of the WEB-INF/lib folder of the WARs.
Even then it depends on implementation details of the server. AFAIK it is not guaranteed to work under the Java EE specification. For example it likely won't work in GlassFish.
Update
I can't tell if the output of your demo is correct because I couldn't find a build file.
Yes, Tomcat does not support EARs, you could use Apache TomEE which is very similar and supports EARs (I don't know if TomEE does classloading in a way that makes this work). In theory you could also make use of the common classloader in Tomcat but that would be quite a hack.
There is a way to do it, using Spring Dynamic Modules, but it requires OSGi environment, which is quite different from simple Tomcat. Few articles worth reading:
Deploying Spring MVC applications to OSGi
Hello world style example
Blueprint - a further development on DM
Another blueprint documentation reference to Spring
That being said there is not a lot of up to date information about Spring with OSGi, but it's worth a try to achieve just what you said (but of course, with additional performance cost)
I am currently compiling a list of third-party libraries used in a web application. The application is deployed in tomcat. I am wondering which of the third-party jars actually must or should be included in the distribution. In particular, I am currently wondering how to best use javax-libraries.
For instance, I would assume the javax.annotation-3.1.1.jar can be used in some standardized way, e.g., downloading it as an extension, without me including it into the distribution of my own piece of software. However, I have it included as a transitive dependency from jaxws-api which I need for web services and therefore it is included in the application's lib directory.
I understand I could use the Extension-List manifest entry to cause the target machine to download and install such jars. However, then they are visible for other applications on the same machine as well which may require other versions of the same libraries.
So, I have some questions about 3rd party libs and I would be very glad if someone could give me some hints:
What is the best practice to use third-party libraries?
Is there some best practice for the javax-libraries?
Can and should I avoid redistribution without imposing a large burden on the person installing the application?
I have to admit, I haven't understood the notion of "redistribution" here, maybe you're using some concrete application server terminology, so I'll try to provide a common answer here, assuming you have a war.
WAR (stands for Web Archive) should include all third-parties used by the application.
These reside in WEB-INF/lib folder.
Now, each Java EE server should "understand" javax libraries, because it contains the relevant interfaces. "javax" libraries usually provide interfaces and the implementation/code that works with these interfaces are provided by the application server developers.
For example for servlets technology, Tomcat (or name any web server) will contain HttpServlet abstract class inside its internal libs, it will scan your war and find where do you implement/extend it, this is how it recognizes your servlets actually.
Now, you shouldn't include servlet-api jar into your war, because its already exists in the application server.
If you're using build tools like maven, they allow to build your war so that some thirdparties will be used for compilation but won't be packed up into war.
I didn't understand why is it so difficult to install the application - in the easiest case - you throw the war into the web server and that's it.
Hope this helps
We have developed a web based application in java(STRUTS 2.0). Now we want to deploy the application. The client is having one pre UAT environment ,UAT environment and a production environment.
Now when we are deploying for pre-UAT we have created the copy of our project and renamed it to pre-UAT. Similarly we are planning for UAT environment and one we already have for development. So in all we will be having 3 copies of our code.
I want to ask is this approach correct or what is the standard approach followed. This is not our final release as we are first releasing a version and then we will be working on other modules.
So please can anyone guide me for approach to follow for creating this 3 different environments.Thanks in advance
I am not sure what you refer to by "we will be having 3 copies of our code". If you are implying that you actually copied the code-base around multiple times, please stop reading and refer to this:
Why is "copy and paste" of code dangerous?
And once you finish reading, do some research about source control and how to use branching/tagging for concurrent development.
If you were referring to multi-environment deployment:
Assuming your application is designed correctly (and I'm treading very carefully here), one WAR file (you were mentioning you're using Tomcat, so I am concluding that your application is packaged as a WAR) should be sufficient. The application code should be environment-independent and should read its environment-specific configuration from external resources, such as a database, configuration files or JNDI.
If your application code is environment-independent, then all you need to do is simply deploy the WAR file to each of the environments (the same WAR file), plus the environment-specific set of external artifacts (such as configuration files).
i have an API that is being written for a large group of 40 or so applications to share.
my problem is currently they plan on having the API as a simple library included in each war file for each program. the problem thats going to occur is when two apps are running on the same instance with different versions of the api library. ive had a lot of problems in the past with this.
i seem to remember a while ago something where i can wrap my library into an ear file or something and deploy it to tomcat to make it global. simply including it in the lib folder won't work because it will include hibernate systems that have to be deployed to allow the api methods to access the database. then in each application i would have an interface i can implement that allows me to call those api methods. very similar to local EJB3 but not as complex and didn't require an enterprise level server to implement.
anyone else remember something like this or was it a bad dream on my part?
You will have problems if you use a single jar shared by all the webapps, since it will then be impossible for two apps to use a different version of a library. But if each webapp has its own version of the library in its WEB-INF/lib, the container shouldn't have any problem: each webapp has its own classloader, which doesn't see the libraries of other webapps.
At our shop, we are maintaining roughly 20 Java EE web applications. Most of these applications are fairly CRUD-like in their architecture, with a few of them being pretty processor intensive calculation applications.
For the deployment of these applications we have been using Hudson set up to monitor our CVS repository. When we have a check-in, the projects are set to be compiled and deployed to our Tomcat 6.0 server (Solaris 10, sparc Dual-core 1.6 GHz processor, 2 GB RAM...not the beefiest machine by any stretch of the imagination...) and, if any unit-tests exist for the project, those are executed and the project is only deployed if the unit-tests pass. This works great.
Now, over time, I've noticed myself that a lot of the projects I create utilize the same .jar files over and over again (Hibernate, POI (Excel output), SQL Server JDBC driver, JSF, ICEFaces, business logic .jar files, etc.). Our practice has been to just keep a folder on our network drive stocked with all the default .jar files we have been using, and when a new project is started we copy this set of .jar files into the new project and go from there...and I feel so dirty every time this happens it has started to keep me up at night. I have been told by my co-workers that it is "extremely difficult" to set up a .jar repository on the tomcat server, which I don't buy for a second...I attribute it to pure laziness and, probably, no desire to learn the best practice. I could be wrong, however, I am just stating my feelings on the matter. This seems to bloat the size of our .war files that get deployed to the server as well.
From my understanding, Tomcat itself has a set of .jar files that are accessible to all applications deployed to it, so I would think we would be able to consolidate all of these duplicate .jar files in all our projects and move them onto the tomcat server. This would involve only updating one .jar file on the server if, for example, we need to update the ICEFaces .jar files to a new version.
Another part of me says that by including only one copy of the .jar files on the server, I might need to keep a copy of the server's lib directory in my development environment as well (i.e. include those .jar files in eclipse dependency).
My gut instinct tells me that I want to move those duplicated .jar files onto the server...will this work?
I think Maven and Ivy were born to help manage JAR dependencies. Maybe you'll find that those are helpful.
As far as the debate about duplicating the JARs in every project versus putting them in the server/lib, I think it hinges on one point: How likely is it that you'll want to upgrade every single application deployed on Tomcat at the same time? Can you ever envision a time where you might have N apps running on that server, and the (N+1)th app could want or require a newer version of a particular JAR?
If you don't mind keeping all the apps in synch, by all means have them use a common library base.
Personally, I think that disk space is cheap. My preference is to duplicate JARs for each app and put them in the WAR file. I like the partitioning. I'd like to see more of it when OSGi becomes more mainstream.
It works most of the time, but you can get into annoying situations where the jar that you have moved into tomcat is trying to make an instance of a class in one of your web application jars, leading to ClassNotFoundException s being thrown. I used to do this, but stopped because of these problems.
I really don't think putting libraries in common/lib is a good idea. The idea behind the use of war files as applications into a servlet container, is to have a real idea of isolation between your webapps. You could face errors like deploy some third party WAR (with it own libraries inside WEB-INF/lib) and it behave unexpectedly because it loaded other version of one of it libraries from the common one (remember that the regular behavior for load classes is first look at the common classloader and if you don't find the class look into the one for your webapp). Don't even mention how painful could be to move some application to other servlet container or an Application Server.
As mentioned before, you could use maven to deal with jar dependencies, and if you like the homogeneous use of libraries, define a POM parent (maven jargon) across all your applications.
In my experience you should be very careful with sharing libraries between web applications by moving them into the web container itself.
Let them live in WEB-INF/lib so your wars are self contained (you WILL be glad you did one day).
What you might consider is employing maven or Ant Ivy to pull in library jars from a common repository instead. This is very useful and should not be a problem in your scenario.
Edit: A notable exception is the Metro library - web service layer from Glassfish - which needs to be in the web container and not in the web application.