About Java EE deployment style, which is better? - java

I have a project, b/s architecture. and with EJB.
So, I can deploy it in two package: a war, and a ejb-jar.
and also, I could deploy it in ONE package: a EAR.
what's the advantage of deploy those two package to ONE ear ?

For me the following quotation (taken from the book "JBoss at work") explains it very well:
An EAR is like a carton of eggs—it keeps everything organized. While the carton doesn’t
add any direct value to your omelet, it makes getting the eggs home from the store so
easy that you wouldn’t think about transporting eggs any other way.
Each egg in your EAR carton is a specific piece of the J2EE puzzle (WAR, EJB, JAR).
edit as suggested by #DavidWallace find a refined answer below...
There is no such thing as an "advantage" of an EAR.
PRO: You can put everthing thing you need to deploy into a single archive.
CON: If you include a vendor specific deployment descriptor (for easy deployment) you might need to repackage the EAR if you want to deploy it into an application server from a different vendor.
At the end it's only a matter of assembling/packaging if you use an EAR or separate modules. Independent from that there is no extra coding needed.

Just my 2 cents to discussion here. If there is dependency between modules (e.g. war components are calling EJBs) I'd vote for single ear deployment, because:
easier management (single install/uninstall, start/stop) and a bit more logical (if you stop just ejb-jar, your web module wont work anyway.
can share some classes via util jars in ear/lib folder instead of duplication in each module or creating external shared lib
can use local interfaces and auto binding of #EJB references
Two separate modules would be better, if:
ejb-jar is shared by many independent applications (web modules) (kind of shared, service layer)
you would like to update web module without affecting ejb module.

Related

How can I reuse a library in multiple WAR/EAR files deployed on an application server?

I'm currently working on an ebanking platform, so out customers are banks. To extend this platform, we develop our own 'xDK' (development kit) for 3rd party developers (usually the banks themselves).
When xDK is used as a dependency (via maven or gradle), it brings along a lot of transitive dependencies in order to work (~25MB). I was trying to think of solutions to make the dependency a bit lighter to use (given that it needs all of its dependencies) which in turn will promote having smaller, more focused services (not exactly micro-services but at least a step closer).
The current situation's benefit is that every service/project can use its own version of xDK and it doesn't have to update until it needs to. The problem is that it doesn't scale. If we assume 100 WAR files having xDK as a dependency, we create a 2.5GB overhead on the application server (even if they all use the same version).
I'll list two options I was thinking of, but I'd like to know if there are better solutions for this problem. Feel free to ask for more info. Thanks in advance.
Similar to JavaEE components (JPA, JAX-RS, ...), we'll have an 'api' dependency and the implementation. The projects will only declare the 'api' as a provided dependency while the implementation will be provided like so:
JBoss module
I haven't worked with other application servers. We (and our customers) only use JBoss EAP, so this might be a JBoss specific solution. We can create a JBoss module for xDK and then make every deployment depend on it via the JBoss deployment descriptor. The benefit is that we get rid of the multiple copies of the library, but we lose on version flexibility. This would mean that there needs to be some kind of governance on which version of xDK you code against in your service. Also, every time there is a breaking change, we'd need to update all services if we want to update the JBoss module to the latest version.
Bundle in an EAR
EARs allow multiple WAR files in them and also jars as libs. xDK will be an EAR dependency. Again, we have the same pros and cons as the previous solution. This solution is JBoss independent. However, it needs an extra build step to collect all the projects and bundle them, which might be annoying for out customers if they need to bundle their own services.
How about using the maven dependency scope of provided to declare that for the individual war files the jar file is provided outside of the war file, and then have another mechanism to inject the shared jar file into the application server?
c.f. https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

Create single web app (WAR) from multiple web applications

We already having an spring web application (maven project) say webApp1 which is hosted on production and working fine but now due some business requirements we want to develop an another web application say webApp2.
So some clients demands both apps, or some either one of them. we need freedom of which module to be deployed, there can be the case where some clients don't want webApp1 so deployment package must include only webApp2 or sometimes both.
Approach 1:
Lets create another maven project and develop individually, at the time of creating deployment package use of Apache Ant can be done which will create WAR file by combining libs,views,controllers of both the applications or of one. combining web.xml,root-context.xml,servlet-context.xml may be the manual task.
Approach 2:
After searching on approach 1 I come to know about EAR (similar question https://stackoverflow.com/a/2936464/1629242).
EAR package (similar question https://stackoverflow.com/a/2936464/1629242) can be the approach, but for this do I need to convert existing application as EAR? or what changes are required in existing working web application webApp1? also how I can control which module need to be added in EAR
As for approach 2. it really depends how exactly do you host your application, what is the container. If it's Tomcat/Jetty which can be a pretty common choice, than EAR is not even an option, since they don't "understand" (can't process) EAR files.
Regarding approach 1. The 'manual' part of combining various xmls can be tedious and certainly error prone. Moreover, if you combine the xmls you won't get a real separation (at the level of classloader) between webapp1 and webapp2. After all totally different applications will be hosted in the same WAR.
So, IMHO, you should go for approach 3:
Keep webapp1 and webapp2 as different deployment units (different WARs). Keep different web.xml, spring configuration files and so forth.
Deploy these wars as 2 different files in the same container. Container will happily serve 2 different Wars. This way, spring beans, servlets, filters and so forth won't interfere between two apps at runtime. Moreover this approach can be fully automated.

I would like to get some suggestion regarding multiple ejb-jars in one ear

I would like to get some advise. I have an application which consist of modules. A module is sliced to 3 parts, so every module has:
- libraries (shared jars, DTOs, beans)
- swing stuffs
- ejb stuffs
The whole is packaged in one ear file and it may contains many ejb jars, currently 3. To handle separated the ejb jars of the particular modules of my application is, I think, the easiest way to manage the whole. Later I would like to use OSGi to handle the modules. But, this is the future.
Every ejb jar has own persistence.xml and it works. I can deploy it, the hibernate creates the tables and I can use my application. But I have that feeling this is not the best or proper solution to handle this "multiple ejb jars in one ear" situation. I would like to know what is the best or proper solution or what is your suggestion.
Thanks in advance!
The way you do it is actually the best OO-solution: you seperate your concerns.
Moreover you also have more flexibility in the current situation: you can leave out or change one of the ejb jar files and your application will still deploy and keep working.

How does a web server/container treat a POJO in respect to other classes like EJB's and Entities?

I'm trying to use plain old java objects(POJO)'s and regular class files where needed and only use EJBs when I need the functionality that they add such as asynchronous calls, pooling, etc. I'm wondering how the server treats this behavior once the project is deployed on a server. Since it is not managed by the container does a new instance have to be created for every stateless session bean pooled that might call one of it's methods? How do things like static methods or state affect this model.
Edit:
1) I can clarify more. The point of Java EE is that you annotate a POJO with #stateless etc so that a container can manage it. You don't have to declare a new instance of a stateless bean you just inject and can make calls to it's type.
2) Most Java EE tutorials and books never mention non annotated classes as a part of your business logic. It's never brought up. This seems strange to me if you can use them in Java EE projects for your business logic and it can get deployed on a server. If you don't need pooling or asynchronous access--the things that a container helps manager through an EJB then you can use theses regular POJO's in your Java EE project.
3) that leads me to my question which is how do I incorporate properly into a project? Do I put them in the EJB project that's connected to an EAR or should they go in the EAR? or Dynamic web project. There is almost no mention or instruction on proper use of regular objects like this. When it gets compiled into a WAR for deployment are there any issues you run into on the server? Isn't it expecting properly annotated EJBs, servlets or JSP?
The don't affect it at all. Classes are classes, objects are objects. They're no managed, they're not interfered with, nothing happens to them. They're not special is any way.
Static singletons are static singletons, Java is java.
All you need to be aware of is the classloader layout of your container, and how it relates to your deployed applications and resources. (Classes in one app can't see classes in another app, for example.) Most of the time it's not really important. Sometimes, it is, as things get more complicated.
But for the most part, it's just Java.
Addenda:
A better way to look at this is to simply group your classes up in to blocks of locality.
Let's take a simple web app that uses EJBs.
The web app is deployed in a WAR artifact, and the EJBs can be deployed separately, as individual EJBs in the container, or, more likely, in an EAR. When you package your application in an EAR, you will likely bundle the WAR within the EAR as well. So, in the end the EAR contains your WAR, and your EJBs.
Now during development, in this case, you're going to have classes that have are in one of three categories.
Classes that are relevant solely to the EJBs (for example the Session Beans).
Classes that are relevant solely to the WARs (such as a Servlet class).
Classes that are relevant to both (a database entity perhaps).
So, a simple way to package them is in three jar files. A jar file for your WAR (in fact, this is the WAR, with the classes in WEB-INF/classes), a jar file for your EJBs, and a jar file for the 3rd type, we'll call that a library.
In terms of build dependency, the WAR build depends on the lib, and the EJB build depends on the lib. But neither the WAR nor EJB depend on each other, as they don't share anything directly, only indirectly through the 3rd library jar. The lib jar is stand alone, since it doesn't have any dependency on either the WAR or EJBs. Note, your EJB Session Bean interface classes will go in to the library jar (since both tiers rely upon them).
In your ear, you simply bundle the lib jar, the WAR, and the EJB jar along with a META-INF dir and an application.xml file. The WAR has its own structure, with the WEB-INF and all, the EJB jar has its META-INF and ejb-jar.xml. But of note is the that lib.jar is NOT in the WEB-INF/lib directory, it's in the EAR bundle and thus shared by both the EJBs and the WAR using class loader chicanery that the container is responsible for.
This is important to note. For example, if you have, say, a simple static Singleton in your lib jar, then BOTH the WAR and EJBs will share that Singleton, since they're all part of the same class loader. To use that Singleton, it's just normal Java. Nothing special there.
If the EJB and WAR were deployed separately, they would EACH need there own copy of the lib.jar, and in the case of the Singleton, they would NOT share it, since each module would have it's own class loader.
So, barring some real burning need otherwise, it's easier to bundle everything in to an EAR and treat both the EJB tier and WAR tier as a single, integrated application.
Addenda 2:
People don't much talk about using classes in Java EE development because there's nothing to talk about, they just use them, like in any Java program. You're over thinking this here.
The 3 jar idiom: war, ejb, lib is one I've used over the years because it separates the 3 concerns, and limits dependencies. Client -> lib -> EJB. It also simplifies the build, since clients typically need just the lib jar and java. In the Netbeans IDE, this is trivial to manage. With minor work, it's straightforward in other IDEs or even in ant/maven. It's not a huge burden, but keeps the 3 parts relatively clean.
Dependency and Jar management is the nightmare of any large Java project, and even more so with EJB when you're dealing with the different deployable artifacts. Anything that can help mitigate that is a win, in my book, and truth is, a clean, stand alone lib jar helps a lot, especially of you need to integrate and use that lib with other code. For example, if you later write an external GUI client using Remote EJBs, or even web services, the lib jar is the only dependency that client has. The benefits of this jar far outweigh the minor pain it takes to set up this kind of library.
In the end the lib jar is just a jar like any other jar you'd want to use in your application (like logging or any other popular 3rd party jars).

Project structure organization: how to make it better?

All -
we have several web applications, all based on some version of Spring developed over time by different team across organizations. They each produce their own WAR, have a different context to work within, and often gets deployed on the same machine, as their functionalities are closely knit together. So we end up with:
tomcat/webapps/{A, B, C ... }
upon deployment, each use a very similar set of tool chains, replicate all Spring jars and dependencies all around.
I am wondering if there is a way to make the project structure better, deploy as a SINGLE war, while allowing each webapp live in their own source repo and have its own pace of development??
Any pointer or references are much appreciated.
Oliver
Deploying in a single WAR will couple all the projects together. Modifying one will mean redeploying all, with the accompanying QA effort to validate and do regression. I wouldn't recommend that.
Multiple copies of Spring JARs can be addressed by putting them in the Tomcat /lib; they're loaded by the Tomcat class loader instead of the WAR class loader. That will mean that every app has to be on the same version of Spring; upgrading one means upgrading all. You'll have to regression test all at once.
What harm is separate WAR files doing you? What do you care if the Tomcat /webapps directory has lots of deployments? One advantage is that they CAN be on separate release schedules. That's a big one to give away. Be sure you have a good reason before doing it.
you would have to probably move to an app server like jboss, but couldn't you use an ear file and have maven build the modules for you? That way you could probably put them in separate repos if you want each with it's own pom and then have another project with a pom for the ear file:
here is the maven ear plugin:
http://maven.apache.org/plugins/maven-ear-plugin/
here is an older blog post about multiple spring app ear file (single applicationContext fo all wars to share if you need):
http://blog.springsource.com/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/
Based on one of your comments to another response, it sounds like you might be more interested in maven's multi-module project feature. This will allow you to define a parent POM with consistent dependencies and project layouts managed across multiple projects.
You might benefit from combining each project into a single WAR, but I do think this is really one of those 'the grass is always greener' problems. One key thing I would keep in mind is figuring out how much longer (or shorter!) is redeployment going to take if the projects were combined.
Think about OSGi. You can deploy all the dependencies just once, build your separate but interrelated modules as OSGi bundles, and deploy and upgrade them all independently. You can also choose whether to deploy them all as WARs (web bundles) or to deploy them as JARs with one or many WARs importing them to tie everything up. Virgo Web Server, formerly Spring DM Server, is really nice and comes ready to do this kind of stuff right out of the box.

Categories

Resources