Understanding EJB in the context of web applications - java

I have been working with J2E web applications for some years now and have started to use EJB over the last few weeks.
I created a project based on this example
Basically I create two maven projects, similar to what is described here https://blog.illucit.com/2015/04/ejb-remoting-with-wildfly/, one that builds a web application(war) and one that builds an EJB.
In web applications pom I add a dependency to my EJB and I can use a context look up to call the correct EJB and cast it to the correct class type. Even though my bean is annotated with remote I am guessing this is a local invocation.
On a second attempt I deployed an EJB module and separably deployed the web application. I was able to do a context look up to pull in the session bean. But I could only cast it to an Object class. I think because I had no reference to the EJB in my web application, as it was part of a separably deployed module, I couldn't do the cast.
I would imagine that since my web applications are seperate, this is a very simple example of a distributed system?
If so, How do I avoid this casting issue, if the class definition is in another application?
Edit-
Because I havent got the awnser I was looking for I have tried to narrow the scope of my question some more.
On this example
https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+server+instance
You can see the client is able to call the Greeter class, even though it is sitting on another server. The client has no import of the Greeter class.
So how is it able to cast the EJB lookup to a class it doesn't have any reference to?

If you want to divide the EJB and the WAR project in different servers you need a third project (normal Java project) with all the objects (POJO, VO, DTO or Entities) that you will use for communicate between WAR and EJB and also you need to put all EJB's Remote interfaces. In this way you can do the "cast". This new project must be a dependency of both projects EJB and WAR.

Related

Glassfish - share EJB web application between nodes

I've got a glassfish server with a couple of EJB wars deployed on several different nodes. I want one of the applications (deployed on node1) to be 'visible' to all applications deployed on different nodes, so that they would be able to inject some remote beans from it. However, I am allowed to have only ONE instance of this application for the wole server, so deploying it separately on all nodes is not possible.
Is this kind of setup possible in glassfish 3.1?
This is achievable through deployment descriptors:
https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#cross-appserverremoteref
In your sun-web.xml (or glassfish-web.xml, both will work in this case) define ejb-ref as follows:
<ejb-ref>
<ejb-ref-name>fooejbref</ejb-ref-name>
<jndi-name>corbaname:iiop:node_name:node_IIOP_port#foo.bar.YourEJBRemote</jndi-name>
</ejb-ref>
It's not exactly convenient - you will need to define that for each remote bean you need, and add such a descriptor in every app that needs it. It should however work, and I don't know of any better way.

Java EE deployment issue

I'm running into some issues in deploying my Java EE application, and could use some advice.
I have 3 components to deploy:
Integration layer (Data): POJOs and CDI Beans - JAR file
Application layer (BL): EJBs, CDI Beans and POJOs - JAR file
Presentation layer: Servlets and such - WAR file
Optimally, I would like to be able to deploy both the integration and application layer JARs in the same Java EE server, but as separate JARs (since I might want to change the hardware configuration later on and separate them into two different servers on two separate machines).
The problem, is that I'm unable to get the CDI injection from the integration layer JAR to the application layer JAR to work. The server says (and probably rightfully so) that it's impossible to resolve the injections.
So far I came up with these possible solutions:
Package the two JARs into a single EAR file (maybe throw in the WAR as well ...), and deploy that
Use JNDI between the different layers (possibly create a CDI producer to do a generic injection based on JNDI names or something like that)
In the integration layer, make the objects being injected into the application layer (the DAOs) EJBs instead of CDI beans
I don't like either of these solutions (especially the last), since they restrict my future deployment options. The second solution does not restrict me, but it might become tedious at some point (when I accumulate a lot of code).
Finally, my question is:
Is there an option I didn't find yet, that would allow me to deploy the two JARs on the same server with the CDI injections working ? Possibly something that would still work if at some point I separate the JARs into different servers ?
Yes, there are other options as well.
Use a java EE container that supports OSGi as well, and use OSGi interface for your deployment dependencies. At least Websphere, Glassfish, JBoss (with jbosgi installed), Jonas support deploying OSGi bundles. This means your modules should be converted into OSGi bundles.
Use a container-specific extension that allows modules to communicate between each other. JBoss as jboss-deployment-structure.xml that you can use to have a dependency to another deployment.
Use a server-provided shared classpath for your dependencies. Wouldn't really recommend this.
My vote would go for OSGi.
None of them will work by themselves however if you deploy packages to different servers. A remote technology like remote EJBs, remote JNDI lookups, Spring remoting, HTTP-based api, CORBA or similar is needed between different servers. In Java EE, EJB is the de-facto standard for this, but Spring remoting is not bad either.
Update: you added that you use TomEE servers. Indeed TomEE won't support the first two options I mentioned. I would use EJB in that case - the fact that you're using EJBs can be abstracted away from the business layer using an EJB delegate, and you could use EJB (stateless session bean) only for the interface part, leaving your DAOs as POJOs.
not sure what your goal is but deploying a war is fine, can even be done manually with these commands:
mkdir -p webapps/myapp/WEB-INF/lib
cp myjar*.jar webapps/myapp/WEB-INF/lib/
If your goal is to be able to split them you can use TomEE skinny war feature.
Create a war with a WEB-INF/jars.txt file.
In this jars.txt put one line by dependency/jar. It can be the path to the jar or maven coordinates.
Once setup it will allow you to change jars one by one then simply restart the server. This is great when several teams work on the same binary.
There are some alternative with TomEE but this one has the advantage to be easy to change to a portable one (war).

Should we use ApacheCXF or EJBs for communicating the logic and web modules?

We are currently developing a web application for college and we would like some advice from a more experienced developer.
We have a backend using Hibernate to operate on a MySQL database. Another project is the web UI that uses the API delivered by the backend (registering user, fetching data associated with certain profiles etc.). We use the JSF framework (RichFaces) for the UI. Everything is built using Maven.
The technology we can't decide on is for the communication between UI and logic modules. The first option is to use ApacheCXF to provide SOAP webservices that UI can be a client of. The second option is to use EJBs to invoke backend methods from the UI module.
What approach is more widely-used? As far as we read on the Web, using EJB is faster than SOAP webservices. On the other hand, we don't have any experience with EJBs using Tomcat (we would prefer using Tomcat since it seems to be a cheaper option, however we don't know what we would have to do in order to use EJBs with Tomcat). Additionally, working with webservices since the beginning will allow us to add support for different platforms (for example, Android).
Another aspect which we are discussing is about how should the application be deployed. The alternatives we have considered right now are:
Deploy it as a single WAR project (which would solve the problem we have about communicating the UI with the backend of our application).
Deploy two WAR projects in the same server using webservices for communication between the projects. (We have a prototype using this approach deployed on a Tomcat server)
Deploy a WAR project and EJB project.
Deploy an EAR project which would contain the references to the WAR and EJB projects. (We have a prototype using this approach deployed on a Glassfish server)
The project right now is starting, so we will only be handling a couple hundreds of users right now. However, if the project succeeds we would need to deal with a couple million of users.
Any advice would be appreciated. Thanks.
Edit: So any advice about how the project should be deployed? Is it necessary to use EAR? Is there any advantage if we deploy the project as an EAR module?
Edit 2: We found the advice we needed on this thread: Deploying java applications (Tomcat/Glassfish)
First things first. I would avoid using Web Services if there's no need for it. If you feel that you might need to call this system from external programs and platforms, then go for it. Even then, I would only use the web service interface for external integration, and still have an internal EJB implementation.
EJBs are awesome for enterprise applications. I would highly recommend that you look into that. They provide support for EJB Pooling, Transactions, Aspect oriented programming, Security, Stateful sessions, Java Messaging, JNDI etc. And you can inject them directly inside a Managed Bean (JSF). You said that you will eventually handle millions of users, so I assume that you will want your application to run as fast as possible, I don't think SOAP web services will be a good fit. Remember that SOAP web services encode messages as text, so if your application will be sending binary files etc, then you'll suffer significant performance issues.
As far as deployment goes I would go with an EAR, or a WAR for the JSF and and EAR backend. you can use Injection to pull the classes you need, even remotely, from multiple web applications and other EAR apps.
I'm not sure why you say Tomcat is Cheaper. Glassfish open source edition is a fully functioning JavaEE6 Server and its free. JBoss is also JavaEE compliant and is free. both of them are used in lots of production environments. I find glassfish to be much more user friendly, and would recommend it to EJB noobs :)
I also started with Tomcat, but now I don't use it at all. why use the servlet container only, when you can have the whole shabang? hope this helps.
we use ApacheCXF at work and its has SOAP and Restful. Reliable and relatively easy to setup. I am not sure why you want to use glassfish maybe it's preference but you can implement your projects in eclipse too. It's really that is up to you and your team and the requirements and skill sets your team may have to build and support, that a side CXF webservice+apache + eclipse with maybe two war files would be a good path.
I wouldn't use web services in this case. You can use managed beans as controllers.
Put the logic into EJBs, views into rich faces and control the flow using managed beans.
If you use maven you can generate a project with the structure of EAR (war for web module and jar for ejbs). I don't remember the name of an archetype but you can find it easily.

Adding a web interface (Spring MVC) to existing Java application

I have an existing Java application (Spring based) that currently does NOT have a web interface, nor does it run in a web container. It packages up nicely with a start program and just works.
What I need to do is add an administrative web interface for some administrative type things, retrieving real time metrics, and perhaps some graphs to give the users a warm fuzzy feeling knowing that everything is working. As we are a Spring shop, and some of our web applications already use Spring MVC it only makes sense to us, however, I'm not happy with the suggestions I've had from our internal Spring folks on how I should procede.
What would be the ideal way to bolt on this web interface?
Convert my application to a web application and have a web container launch the application. I not too keen on this approach is the web tier is really secondary to the primary application.
Create a separate project that packages as a war, embed Jetty in my existing app and have it load the war. I think I can use the context loader listener to make the root context of my application the parent to the web application spring context. This would involve breaking up my Maven project into 2 projects I believe. I can't use an existing web technology for communication between the web tier and the primary application as my primary application is not web enabled.
Embed Jetty and put the Spring MVC stuff directly in my app. While I've done this approach before, it does involve some ugliness - for instance exploding the JSP tag libs into my jar.
Any thoughts on some clean separation here?
Also of note, my current jar contains some utility applications which some shell scripts launch. Going a pure WAR route would make this not so easy, since I can't juse point java at my war file and choose a class to execute.
Thanks.
If it's true that web is just a minor addition the application, migrating it to WAR and deploying in servlet container might be an overkill. Embedding web server/servlet container looks much simpler, although it doesn't have to be Jetty or Tomcat. You can use web server built into JDK or write one on top of netty or even raw sockets. But that's a hell to maintain.
Yet another solution to springs to mymind when reading:
web interface for some administrative type things, retrieving real time metrics, and perhaps some graphs
Maybe you don't need an interface, but monitoring infrastructure instead? Check out JMX (Spring has great support for JMX) - and write a second web application that simply connects to your standalone Java app via JMX and displays the metrics in fancy way. Another approach is to expose JMX via Jolokia, which translates JMX to REST services.
This approach has several advantages:
monitoring API is universal, and you get it for free
you don't have to use web client, monitoring application is completely decoupled,
finally changes to your original application are minimal. Check out this proof of concept: 1, 2.
It really depends on the structure of your existing Java/Spring app and how much of an API it provides. I've done something similar to this and I approached it by creating a separate Spring MVC project and then specified the existing Java app as a JAR dependency.
This is easy with Maven (or Ivy, etc) and provides nice decoupling. The trick is to be able to write service classes in the Spring MVC app which then access data via your dependent Spring app via a simple DAO class. That's why I stated at the beginning, that it depends on the structure of your original Java app. It has to be able to provide an API for data access that you can then plug your DAO (impl) into.
If this is not easily done, then the next option I'd suggest is simply converting your Spring app to a Spring MVC app. I've worked on another app where we did this. Using Maven, its possible to specify that the build can create either a war file or a jar file (or both). So it can be deployed as either a webapp (via war) or a normal app (via jar). Yes, the jar version has a bit of bloat but its a worthwhile compromise.
The question of embedding Jetty or using Tomcat via a war file is a completely separate issue that has its pros and cons. It shouldn't affect the approach you take in architecting the web app in the first place.

EJB3 Local and Remote interfaces

I understood that Local interface is designed for clients in the same container's JVM instance and remote interface is designed for clients residing outside the EJB container's JVM. How about the web application client which is not reside (or packaged) in the same .ear but reside on the same Java EE server?
Officially #Local annotated beans can only be accessed if they're in the same application. A .war deployed separately from an .ear (or other .war or other .jar EJB) is a different application, even when deployed to the same application server instance.
There's thus no guarantee that the code in your .war can call #Local EJB beans that are defined in the .ear.
However, in practice in nearly all application servers this just works.
There's a request for the EJB 3.2 spec to officially support local cross-application calls: https://download.oracle.com/otndocs/jcp/ejb-3_2-fr-spec
Local interfaces are to be used in communication within the same application. It doesn't necessarily mean JVM.
The point is: even within the same JVM instance, on the same server, two different applications cannot communicate using local interfaces (which means local and no-interface views).
If you have a web component (WAR) as well as a business component (EJB-JAR) which is in the same application, the most intuitive and straightforward solution is to package them in one EAR or in one WAR (since Java EE 6).
You use the remote interfaces, but you make a lookup using JNDI (that's how i'd do it), this way you find the instance of the EJB in the server and can use it in your web application.
Although you still need a jar with the EJB interfaces in the web application project.
EDIT and I agree with JB Nizet, why would you want the WAR outside the EAR?
Remote interfaces can be called across applications, from everywhere within the application server as well as from outside, even from other hosts.
So assume that you need remote (#Remote) interface. In EJB 3.1 you can use dependency injection.

Categories