Those days everybody talks about microservices and containerless deployments using fat-jars, and framework like Dropwizard or Springboot support you with that. With all the EE components available as separate implementations it should be possible to assemble your own jar of the required componentes (i.e. Weld, Jersey, Jetty).
When using Java EE based CDI, there is this concept of BDA (Bean Deplyoment Archive), that defines a set of CDI-enabled Beans bundled in jar, together with a beans.xml containing some additional information for the BDA, like interceptors.
How do I combine those BDAs into a single uber-jar without loosing the information of the beans.xml? The maven jar-with-dependencies just copies all files into one, overriding the previous file (or keeping the first one, don't know exactly).
Is the concept of a fat-jar compatible with EE CDI at all? Won't some CDI semantics get lost when being all merged into one BDA, i.e. scope of Alternatives.
Here's a tip from the weld guys http://weld.cdi-spec.org/documentation/#5
Basically,make sure you aggregate your extensions and include a valid beans.xml
Related
I have recently started on Java EE and having a tough time understanding it. I have read some answers here on SO but I still feel like there are some gaps in my understading. Basically, Java EE is a specification and application servers like TOMCAT, Glassfish etc., have the concrete implementations. Also, anyone can provide implementation for EE.
So, I have downloaded javax.sevlet-api-4.0.1-sources.jar from Maven repo and I can see that they are just Interfaces and I assume we just use them to build the project?
In tomcat lib folder there is a servlet-api.jar. is this the tomcat implementation of Servlet? and if it is, then is it possible to replace it with another servlet version implementation?
Now, Hibernate is the implementation of Persistence API. if i want to use Hibernate with Tomcat. I just need to add the Hibernate related jars to my application and can use them for both build and run? without actually getting the contract classes.
You need the servlet-api jar file when compiling your code, because that's where e.g. HttpServletRequest is. You don't need to include that jar with your application, because it is provided already by the Servlet Container you deploy your war file to, e.g. Tomcat.
With Tomcat, the implementation of the various servlet classes are in catalina.jar, at least for Tomcat 9, e.g. ApplicationHttpRequest is the class implementing HttpServletRequest. You don't need this to compile your code.
To be accurate, Tomcat is not a fully fledged JavaEE container, it only handles part of the JavaEE spec (mainly servlet, jsp, jndi and a few others).
And as Andreas wrote you need serlvet-api.jar to compile your code (otherwise HttpSerlvetRequest will miss), but as tomcat already provides it (as an interface) as well as an actual implementation, you should add it as a "provided" dependency in your maven file.
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
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).
I have noticed from several web pages that apparently Spring 3.0 supports #Inject from JSR-330. As we would really like to use JSR-299 syntax for dependency injection in our libraries for both web apps and stand-alone applications, and have alternatives to Weld, it would be nice if Spring could do this.
Being a novice to Spring, I tried downloading the Spring Framework distribution and put all jars on the Eclipse build path. No Inject annotation so my existing test project using Weld did not compile.
Can this be done with Spring? What do I need to do to get it running?
(I am aware that Guice eventually will support this too. It is only in SVN for now, and if there is an official Spring release which can, that would be better.)
It can be done. The JSR-330 jar must be downloaded seperately, and cglib to parse the manually written #Configuration classes, plus a commons logging implementation.
The largest difference from Weld seems to be that the wiring needs to be manually written instead of magically found (a bit more cumbersome, but may make more robust applications), plus the startup time is much less. I am still new to Spring - is there a way to have #Configuration classes autodiscovered?
From the Spring 3.0.x Reference documentation:
JSR 330's #Inject annotation can be used in place of Spring's #Autowired in the examples below. #Inject does not have a required property unlike Spring's #Autowire annotation which has a required property to indicate if the value being injected is optional. This behavior is enabled automatically if you have the JSR 330 JAR on the classpath.
So you can make your code agnostic of the DI framework by using #Inject, but you still need to include a jar with the javax.inject classes in your project because Spring does not ship them itself. You can find the relevant jar in the downloads section at JSR-330's Google Code site.
The javax.inject package is not included as part of Spring 3, but it does support it if it's present.
If you look at the source for AutowiredAnnotationBeanPostProcessor, you'll see the constructor uses reflection to locate javax.inject.Inject, and logs a message if it finds it. There's no compile-time dependency on it.
You'll need to locate the JSR-330 JARs from some other source (e.g. the JavaEE 6 SDK).
I have a newbie question as it relates to EJBs. When we compose a web application, all the jsp's/servlets etc are organized/packed into a war file which is deployed on to the server, when it comes to session beans and their deployment, are they treated as container level components that dont belong to any individual application?
No, they're not. EJBs should be packaged into a JAR (so called EJB-JAR) and then assembled into an EAR (that wraps EJB-JAR(s), WAR(s) and RAR(s)). Packaging EJB 3 Applications is a very good article (from the authors of EJB 3 in Action) on this topic and covers classloading, packaging and deployment of Java EE modules. Highly recommended.
Since Java EE 6, it is possible to deploy EJBs as part of a WAR (either put EJB-JARs in WEB-INF/lib or the classes directly in WEB-INF/classes). Note that all the classes are then loaded with the same classloader in this scenario (contrary to the EAR packaging). If you don't have strong modularization needs (which is the case of most applications), this is very interesting because simpler. Of course, the EAR packaging is still available for those with more advanced modularization requirements.