Inject Application scoped CDI bean into stateless EJB bean - java-ee-6

First I will describe what I am trying to accomplish here. I have a Java application that periodically reads data and calls stateless EJB on JBoss AS 7.1.1 for further operations (computing data and saving it into the DB). Then I have front end which uses JSF 2.0. In controller which is a #ApplicationScoped CDI bean and resides in JSF project I inject EJB into it. Now I need EJB for getting data from the DB. I am using #ApplicationScoped CDI bean because of this reason:
The application context is shared between all servlet requests, web service invocations, EJB remote method invocations, EJB asynchronous method invocations, EJB timeouts and message deliveries to message-driven beans that execute within the same application. The application context is destroyed when the application is shut down.
I want only one CDI bean for all the clients, because the data is independent of the user.
Now I want to update data in #ApplicationScoped CDI bean, which is defined under JSF project with the help of EJB bean, which method is executed when new data arrives. I have already successfully used #Inject in #ApplicationScoped CDI bean, where I have injected EJB from EJB project. Now I want to do the other way around. I tried to inject ApplicationScoped CDI bean from JSF project into EJB bean. But when I wrote this I got #Inject underline as warning:
#Inject
private CurrentDataController currentDataController;
The warning is:
No bean is eligible for injection to the injection point [JSR-299 §5.2.1]
When I try to publish project I get error about class not found exception for CurrentDataController.
Caused by: java.lang.ClassNotFoundException: controllers.CurrentDataController from [Module "deployment.TestEAR.ear.TestEJB.jar:main" from Service Module Loader]
It seems that the EJB project can't reference class in JSF project. Also it is looking for CurentDataController class in TestEJB.jar instead of in the TestJSF.jar. What I am missing here?
The structure of my whole project is as follow:
TestEAR
TestEJB
TestEJBClient
TestJPA
TestJSF
Now I reckon that after I will fix the error about no class definition found I will have another problem connected with the warning I have posted.

In an EAR the EJB modules (jar) don't have visibility on the Web modules (war). EJB module is UI agnostic so it's normal to have this layer decoupling.
To resolve you issue you have two options.
Move the bean that need to be injected in your EJB in one EJB module (the war would also be able to inject that bean)
Refactor your app to have only a war (yes you can have EJB in war now). Architecture would be simplier and full EJB will work under JBoss (remote EJB too)

Related

invoke ejb classes using jndi

I have 2 separate projects.
the first project is based on jboss server and implements ejb classes.
the second project is a rest api using the play server.
I want to invoke ejb classes from rest api using jndi .
Have someone any idea how to to invoke ejb classes from client side : we want to package ejb class and transform it into a jar that we want to use it in client side.

How to inject EntityManager in a MDB which is configured in ejb-jar.xml

I have demo application with JPA 2.1 and weblogic 12.1.3 deployment works fine and am able to get EntityManager which is annotated on the stateless bean.
I have application where I have ejb-jar.xml, on this file we have configured all MDB and session beans, Note: application is not using annotation.
And ejb-jar.xml uses http://java.sun.com/dtd/ejb-jar_2_0.dtd(ejb 2), but our application is running on weblogic 12.1.3. On this configuration, I tried to get EntityManager with the help of annotation in MDB, but am getting null object.
Question.
1. Is it possible to annotate EntityManager, with above configuration.
2. If not possible what are alternative ways. meaning I need to move all the configuration of ejb-jar.xml to annotation.
Thanks
Daya

How to call separately deployed ejb3 on wildlfy

As long as my EJB is deployed inside the war of the app using it everything works fine, I only have to #Inject it, no xml, and no local or remote interfaces. The webapp is a Vaadin 7.5.6 app using vaadin-cdi.
When deploying the ejb as a separate jar, the web-app calling it fails with "Forbidden". I've annotated it with
#SecurityDomain("other")
#RolesAllowed({ "guest" })
However, still "Forbidden". Probably some config is needed in the webapp as well. All examples I've found so far mentions jndi-lookup, ejb-jar.xml, web.xml, jboss-ejb.xml, ejb interfaces and whatnot. Is it even possible to have the ejb deployed separately and accessible, while avoiding all this extra config? I'd like to break up my app so that I don't have to deploy everything each time I make changes to the gui, but if I have to revert to "old school" ejb config I'm not sure there is a point.
Using Wildfly 9.0.2, Java 8 and Maven.
Edit:
EJB : The Hello World EJB lives in a maven sub-project, it has jar-packaging. It has no xml-configuration and no local or remote interface. There is no usage of maven-ejb-plugin. The implementation looks like this:
import javax.ejb.Stateless;
#Stateless
public class ReceptionService {
public String welcome() {
return "Hello, Developer! No XML, No Configuration, and it works!";
}
}
There is also a number of real-world session beans that use JPA inside methods that look like this (below) so there might be some persistence and transaction issues popping up as well here, but not until the simple hello-world case is working. The hello-world-webapp does not include any of these EJBs, just the simple hello-world-EJB.
#Stateless
#TransactionManagement(value = TransactionManagementType.CONTAINER)
public class DealerSession {
private Logger logger = LoggerFactory.getLogger(DealerSession.class);
#PersistenceContext(unitName = "MyUnit")
protected EntityManager em;
#TransactionAttribute(REQUIRED)
public Long create(DealerUpdate update) {
notNull(update, "update"); // and so on ....
The persistence unit is defined in the EJB project, and it connects to an datasource in Wildfly. In the real-world-beans transactions are rolled back on failure.
WAR : This is a Vaadin 7 webapp. It simply looks like this:
#CDIUI("")
#Theme("valo")
public class WelcomePage extends UI {
#Inject
ReceptionService service;
#Override
protected void init(VaadinRequest request) {
setSizeFull();
String message = service.welcome();
Label label = new Label("this is the message: " + message);
setContent(new HorizontalLayout(label));
} ....
The EJB jar-file is referenced in the dependencies. So it is included, and everything works as if the EJB bean was just a .class-file in the war. This is very convenient, because there is almost no configuration involved. But as the real-world-project here grows, I'd like to split up the deployment, so that I do not have to deploy all EJBs as part of the war each time the gui is updated, because it slows down the development cycle.
The war project depends on vaadin-cdi 1.0.3 and vaadin-bom 7.5.6, and of course the jar with the EJB (which has jar and not ejb packaging). Also vaadin-maven-plugin, maven-resource-plugin and maven-war-plugin is used.
Both projects also use wildly-plugin 1.0.2.Final. and depend on java javaee-api 7.0.
NOW, my naïve attempt so far has been to change packaging of the EJB jar to "ejb", add maven-ejb-plugin, specify scope provided in the dependency in the pom file of the war-project, and deploy war and jar separately. So far there are no error-messages or warning, both are deployed. But access to the ejb is "Forbidden", there is an error message in the gui saying that, strangely not in the wildfly console. I've tried to add #SecurityDomain and #RolesAllowed annotations to the EJB (see above), but stuff has to be configured on the webapp as well. If it is so that CDI only will inject the EJB as a pojo anyway, or I have to add Local and/or Remote interfaces, perform JNDI-lookups, add lots of stuff to xml configuration files and so on, I can manage that, because there are sample apps and documentation for that, but also everything gets a lot more complicated, and I want to avoid that.
First of all your EJBs are not not injected as such, even if they are deployed with your WAR. This is because you don't declare interfaces. In this case you will at least have to annotate them with #LocalBean which declares the no-interface-view for the bean.
When you outsource the EJBs into a jar, CDI is not able to inject the bean isntances that would be produced by EJB (the proxies) but injects pojo instances instead. To avoid this you could create a producer field or method for each EJB in your WAR. Injecting the bean with CDI then calls the producer. This producer would have to do a specific JNDI lookup (java:global/...) to get the EJB bean instance.
Then, when deploying to wildfly, you will have to add a dependency from the WAR to the JAR since both deployments have separate class loaders and can't see each other. The dependency connects both class loaders so that the one of the WAR is able to load classes of the JAR.
You will only have to activate CDI for the WAR not the JAR in this case since the EJB instances are retrieved by explicit JNDI lookups.
The answer I have approved for my question might be the right one if you absolutely need to use cdi-injection. I never came as far as I got it working, though.
Instead I decided to try use the #EJB annotation, instead of #Inject. When I deploy my ejb (in a separate jar from my web-app, that lives in a war-file) Wildfly registers jndi-names and reports this in the console. One of the names is "java:global/template-service-1.0.0-SNAPSHOT/ReceptionService". Note the "global" scope.
The #EJB annotation has a parameter called mappedName. Injecting and using the ejb like this did the trick:
#EJB(mappedName = "java:global/template-service-1.0.0-SNAPSHOT/ReceptionService")
ReceptionService service;
#Override
protected void init(VaadinRequest request) {
UI.getCurrent().setLocale(new Locale("nb","no"));
setSizeFull();
String message = service.welcome();
Label label = new Label("message: " + message);
setContent(new HorizontalLayout(label));
}
It is also still needed to register module dependency, so that the client class loader can see the service. I do it in the webapp pom.xml using the war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>deployment.template-service-1.0.0-SNAPSHOT.jar</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
This way I am able to deploy my ejbs separately, and I can then deploy my war-file as a "thin" deployment. My real-world project has a bunch of ejbs and jpa-stuff which slows down the develops-compile-deploy cycle when I work on the gut-stuff, with this setup I can save quite some time when fiddling with the gui.
The EJB looks like this, no ejb-jar.xml.
#Stateless
public class ReceptionService {
public String welcome() {
return "Hello, Developer! No XML, No Configuration, and it works!!!";
}
}
The no-xml-part in the message would only be true if you added the module dependency to your manifest manually, and not using war-plugin :o)
Edit: to include dependencies in the ejb jar one can use one-jar plugin or similar.

Separate JSF and EJB apps

How do I use a deployed EJB app from a separate JSF application?
I'm attempting to separate the two applications and access the EJB through the remote interface. To do this I have two eclipse projects - one contains the EJB and persistence logic, tested independently and works. I then created a JSF project that references the EJB project (so I gain access to the remote interface), however this fails when attempting to either inject the EJB instance or lookup the JNDI name (I've tried several variants to no avail). This is what my JSF backing bean contains:
#EJB(lookup="java:global/LocEJB/LocalityEJB!com.ame.business.LocalityEJBRemote")
private LocalityEJBRemote locality;
This is on Glassfish, and I am only referencing the EJB project and not packaging it with the JSF project. When I do the latter, I receive error initializing EJB container problems on the JSF project. So, how do I access the remote EJB and does the way I'm approaching this make any sense?
Thanks in advance!
Your JSF application has to know about the EJB interfaces (at least they did on EJB 2.0). You're using the Proxy pattern to hide the fact that this is a remote component from your JSF client.
First of all you can not use Local interface if trying to access outside the container. You must use Remote Interface.
You can define your Remote interface in the sun-web.xml or EJB injection in the bean.
sun-web.xml code:
<ejb-ref>
<ejb-ref-name>com.xxx.session.UserRemote</ejb-ref-name>
<jndi-name>corbaname:iiop:127.0.0.xxx:3700#com.xxx.session.UserRemote</jndi-name>
</ejb-ref>
Another thing you must have Remote interfaces in your classpath.

Static Object in Jboss using EJB3

is it possible to create something like static object using EJB3 in Jboss. in other words i need to create something like a static object using singleton pattern or something like that, that is because i need to preload a configuration from database and i want that every bean that jboss creates uses this class to read this configuration instead of that every bean load it from the database.
Cheers,
EJB 3.1 does have a standard #Singleton annotation but EJB 3.0 doesn't. However, JBoss offers a JBoss extension to the EJB 3.0 spec to create a singleton with the #Service annotation.
From the JBoss EJB 3.0 Reference Documentation:
Chapter 6. JBoss EJB 3.0 extensions
JBoss provides a few extensions to the
EJB 3.0 spec. This chapter describes
those features here.
6.1. #Service EJBs
An extension offered by JBoss EJB 3.0
is the notion of a
#org.jboss.annotation.ejb.Service
annotated bean. They are singleton
beans and are not pooled, so only one
instance of the bean exists in the
server. They can have both #Remote and
#Local interfaces so they can be
accessed by java clients. When
different clients look up the
interfaces for #Service beans, all
clients will work on the same instance
of the bean on the server. When
installing the bean it gets given a
JMX ObjectName in the MBean server it
runs on. The default is
jboss.j2ee:service=EJB3,name=<Fully qualified name of #Service bean>,type=service
You can override this default
ObjectName by specifying the
objectName attribute of the
#Service annotation.
References
JBoss EJB 3.0 Reference Documentation
6.1. #Service EJBs
JBoss EJB3 Tutorials
Chapter 28. Service POJOs (JBoss extension of EJB3)
Bean with #Singleton annotation should work. Place your database initialize code in #PostConstruct & can release/cleanup in #PreDestroy.