Exposing EJB as REST service packed into EAR module (no WAR) - java

i'm new to Java RESTful development and i need to implement some REST services on top of existing 3.1 EJBs.
I have an existing enterprise application which consists of an ejb-jar and some other jars packed into an EAR and deployed into Wildfly 10.
I've seen many examples out there where a WAR module is used and the class javax.ws.rs.core.Application is used as well.
I am aware of using annotations like Path etc. on my resource classes.
But my question is: can i build these REST services from my existing EJBs without using a WAR ? I would like to keep my modules unchanged (just EAR with ejb-jar).
Thank you so much.

Related

jersey REST layer for existing project

I'm working on project which has an existing war file containing java code. Currently this project is deployed on tomcat but war is not placed in webapps, it is in different location and referenced in tomcat using file containing following in Catalina/localhost folder.
<Context docBase="war path/<file.war>" unPackWAR="false"/>
My requirement is to design a restful webservices for this existing project. I have setup a standalone dynamic web project with Jersey REST setup and its working fine. Whenever a rest call will be made it needs to call its underlying api(existing one).
Note: Both the projects are deployed on same tomcat container, but existing war project file is un-extracted and resides in different location.
Also i dont want to combine both the project into single war.
Could some help me figure out how to call the existing java functions from new REST project?
Can JMX connection work in this case or is that recommended?
Appreciate your help!
Thanks,

Creating EJB remote references into a client witout EAR

Well, this is my development environment:
I am using Java 1.8 and Eclipse 4.5.1 (Mars), J2EE tools and plugins installed to work with WildFly 8 as Application Server
I created a Java EJB project, with a simple HelloWorld stateless session bean class. It implements 2 interfaces: #Remote and/or #Local, where I defined a String getHelloWorld() stub.
Now, I have my client for consuming the EJB: A Dynamic Web Project with one Servlet.
Inside the servlet, I can inject the ejb class using annotations, like this:
#EJB
private HelloWorldLocal bean;
or
#EJB
private HelloWorldRemote bean;
As you see, I declared the bean as HelloWorldLocal/HelloWorldRemote types. However, if I want to deploy and run my application,
I need to put the EJB and Web projects into an EAR first. That allows the Servlet to know and compile the HelloWorldLocal or HelloWorldRemote bean types, by simply adding the EJB project on
the Build Path as Project, or even by putting the EJB project as a Deployment Assembly directive.
I'd like to create a client outside the EAR (a remote Swing application or Remote WebSite). That means my client will
have not the chance to adding the EJB project interfaces as project references in the build path as I did with the EAR. Even if I want to call
the remote bean with JNDI, I need to cast the lookup() object to those types in order to use the bean methods.
The question is:
How can I get the HelloWorldRemote/HelloWorldLocal bean types from my remote client without EARs, if those interfaces are declared into an separate EJB Project?
(Of course, I dont want to create a .jar with the EJB project here).
And what about portable JNDI lookup? https://docs.oracle.com/cd/E19798-01/821-1841/girgn/index.html It should work if the EJB in the same JVM as your client.
I'm not sure I completely understand what you're asking, and I haven't done this in years, but the normal approach for this would to to create an EJB client JAR containing only the client's bean dependencies and remote interfaces. To best accomplish this, you'll want to use a tool such as Maven to build your project which contains an EJB plugin for this. If you're not using Maven, you're going to be limited by the tooling within Eclipse, though at one point it did contain EJB client generation support. The Wildfly documentation on EJB client setup might help also, but explicitly mentions that packaging the client is out of scope.
I'd like to share the only one solution that I found: I have to create a .jar file, with all the EJB interfaces (#Remote, #Local, and so on), and use it like referenced types on my remote clients.
This .jar would be outside any EAR. however, it needs jboss-client.jar because of the # annotations. So, I packaged all, interfaces and jboss-client.jar, exported them to a .jar and I added this new file in my EJB and clients projects as external jar! Now I am able to use the HelloWorld* types on EJB classes implementations and #EJB client variables.
If I want a remote Web client, I've placed the EJB project with a Web Project module, into a EAR - Definitely we need an EAR. The Web module has Servlets, and the servlets handles the #EJB variables and responses. So, Outside this EAR, I just need to use URL's to the servlets and, you got it: EJB method results are reached from remote web clients.
In desktop applications with JNDI, I just put the interfaces .jar like external jar into the client project. In that way, I can cast the .lookup() to HelloWorld* types and using its methods.
I hope it helps.

Is the jndi.properties file required for a EJB + web application (JBoss 5)?

In a JBoss 5 JEE project which I have inherited, the web application (WAR) project contains a JNDI configuration file which seems to be unneccessary. Its content is
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost:1099
Removing it has no obvious effect, deployment and execution works well and unit tests show no errors.
Is it safe to delete this file?
You would create that file if you want to create a -client- that connects to a JNDI context to invoke EJBs remotely. If that war is part of the application that serves the EJB, you indeed do not need it since you already have local access to the JNDI context. Assuming the war is part of an EAR that also holds the EJB module.

Glassfish: modify deployment descriptors for EAR during deployment

After several days of searching, trying and head-banging, I post this question to SO although it seems to be answered already.
Here is the scenario:
I have an EAR application containing (for the moment) one WAR and one EJB module. The EJB module uses JPA (persistence.xml) and some Stateless Session Beans are exposed via Web Services. The web services use Basic authentication with a jdbc realm. The web module uses form authentication with the same realm.
The requirement:
I need to be able to deploy this application either on different servers (dev/test/prod) or on the same server (or cluster) with different deployment descriptors. The deployment settings that need to be different in each application instance are:
The jta-data-source in persistence.xml
The realm-name in web.xml
The javax.faces.PROJECT_STAGE in web.xml
The webservice-endpoint\endpoint-address-uri and login-config\realm in glassfish-ejb-jar.xml
The context-root in application.xml (i could move it to web.xml if it made any difference, see below)
The realm in glassfish-application.xml
During my research, I managed the following:
I can override the javax.faces.PROJECT_STAGE using asadmin set-web-context-param
I can override all settings in glassfish-ejb-jar.xml using a deployment plan during asadmin deploy
The same applies for glassfish-application.xml
I can probably override context-root during asadmin deploy (I don't know how would this work with more than one web modules in the EAR)
So far so good. This leaves me with the following problems:
How can I easily modify the the realm-name in web.xml?
How can I easily modify the jta-data-source in persistence.xml?
By easily I mean during deployment or using something similar to a deployment plan jar. Maintaining multiple copies of ejb.jar or war just with a modified .xml file is not an option.
Just to be clear, the need is to have different databases (either in different stages of development or for different customers) using the same application. The application uses one persistence-unit but it needs to point to different databases (hence the jta-data-source). The realm is a jdbc realm (on the same database) that also needs to be different per application instance.
Any help or pointer would be greatly appreciated.
Have you thought about preparing templates for the deployment descriptors, and populating them with value from property file during build? If you are using ant, you can use the expandproperties filter.
You can do all those things with a deployment plan jar.
It looks like the content of the deployment plan jar is pushed into archive/directory tree of the application BEFORE any of the heavy lifting associated with deployment happens.
See
http://java.net/projects/glassfish/sources/svn/content/trunk/main/appserver/deployment/javaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java
and
http://java.net/projects/glassfish/sources/svn/content/trunk/main/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java

Deploying multi-tier application

I want to build and deploy my first Java EE 6 multi-tier application, with web and business tiers running on separate physical servers on Glassfish 3.1.
I think I understand what's required from a theoretical hi-level view but am not clear on the specifics and small details.
My current plan as is follows:
Create a Maven Enterprise Application in NetBeans 7.
Expose Session Facade EJBs via remote interface.
Have JSF Backing Beans utilise Session Facade EJBs via JNDI lookup.
Deploy EJB JAR to one server and web WAR to the other.
I'd really appreciate some pointers on:
Application structure.
Correct JNDI lookup with separate servers. Is injection possible?
Building appropriate archives.
Deployment configuration to allow tiers to communicate.
Unless you know you will be serving many requests per second, or have very data and/or CPU-heavy business logic, then you should be perfectly fine starting out by deploying both tiers on the same application server. Starting out by deploying to a single Glassfish application server using local interfaces lets you skip a lot of complexity in the runtime environment.
This in turn will allow you to use the simplest form of #EJB-injection in the web tier to access the session facades in the business tier. Local intefaces are faster because the application server can pass references rather than RMI proxies between the tiers and it lets you skip the JNDI lookups. You can always change the annotation later on, or introduce remote interfaces if you later find other reasons to deploy the tiers on separate servers.
Glassfish supports clustering, so you might never have to explicitly separate the two tiers--it all depends on the actual usage patterns, so performance monitoring is key.
Deploying the web tier as a WAR and the business logic as an EJB jar is the right thing to do. Depending on the size and the logical structure of your application, you might want to break that down into to multiple modules.
Maven takes care of building the archives. Make sure you define a sub-project for each war and jar archive, plus a sub-project for assembling the EAR-file. The latter project will pull in the war and jar files produced by the other sub-projects. String all the projects together with a master maven project and voila, you have the flexibility to build each component separately, build the entire thing, or any combination in-between.
You have chosen a hard path, as others have pointed out in comments and answers...
Let's start with the structure of your app(s). You are going to end up with four achives... two that you will deploy:
a "regular" jar for the Remote interface of your EJB (jar-of-interfaces)
an EJB jar that has the implementation of your EJB
an EAR archive that will contain the jar-of-interfaces (in the /lib subdirectory) and the EJB jar (in the 'root').
a WAR file that contains the code that uses the Remote interface of your EJB. This will have the jar-of-interfaces in WEB-INF/lib.
The rest of this answer is based on the EJB FAQ. The most applicable part of that document is here.
You can inject the EJB into the ManagedBean. You will not need to use a dot-lookup method in your ManagedBean.
You will need to use the corbaname for your bean in the glassfish-web.xml file.

Categories

Resources