How to call separately deployed ejb3 on wildlfy - deployment

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.

Related

Inject Application scoped CDI bean into stateless EJB bean

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)

Glassfish V3.1 Invalid ejb jar it contains zero ejb

I'm just about migrating from JBoss 6.1 to Glassfish 3.1 (don't ask why). The following occurs:
Invalid ejb jar [mmsUserMgmtAct-0.0.1-SNAPSHOT.jar]: it contains zero ejb
...
Note:
1. A valid ejb jar requires at least one session, entity (1.x/2.x style), or message-
driven bean.
2. EJB3+ entity beans (#Entity) are POJOs and please package them as library jar.
3. If the jar file contains valid EJBs which are annotated with EJB component level
annotations (#Stateless, #Stateful, #MessageDriven, #Singleton), please check server.log
to see whether the annotations were processed properly.
As everything was running perfectly with Jboss I can swear there are EJBs within the jars. The only thing which might cause the error is the fact, that I splitted the interfaces (#Remote and #Local) plus the entities (#Entity) into a package xyzService.jar and the stateless bean (#Stateless, #Remote(XyzService.class)) into another archive named xyzServiceImpl.jar.
All packaging was generated by maven, so no issues with this. Maybe I should mention that I simply copied the things into autodeploy folder.
Any glues?
Thx in advance
El Subcomandante

OSGi JAX-RS and bnd declarative service

I want to migrate my EE application to OSGi. my application consist of business libraries, database JPA/Entities and a REST/WS interfaces. it also has a web client.
I start by prototyping the structure and making all the interfaces and bundles talking to each other in OSGi clean way. I want to use a clean specification as much as possible without any specific vendor or framework.
I am using bnd maven plugin to generate the manifest and the declarative services. I want to make a call from my rest resources to an OSGI service (on another bundle) using injection like so:
#Path("some-resources")
#Component
public class SomeResources{
private SomeService service = null;
#Reference
public void setController(SomeService service) { // <- this is never called
this.service = service;
}
#GET
#Produces(javax.ws.rs.core.MediaType.APPLICATION_XML)
public Object getSomeService() { // <- called
try {
service.process("Hello World"); // <- Error null object
}
...
}
Can i annotate the resource with bnd #Component and can the #Resource be injected?
everything works fine but the service is always null.
What should be the way to declare my bundle for BND to make it a web/wab package?
I use maven bundle:
<packaging>bundle</packaging>
...
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.7</version>
<extensions>true</extensions>
<dependencies>
<dependency>
<groupId>biz.aQute</groupId>
<artifactId>bndlib</artifactId>
<version>1.50.0</version>
</dependency>
</dependencies>
<configuration>
<supportedProjectTypes>
<supportedProjectType>ejb</supportedProjectType>
<supportedProjectType>war</supportedProjectType>
<supportedProjectType>wab</supportedProjectType>
<supportedProjectType>bundle</supportedProjectType>
<supportedProjectType>jar</supportedProjectType>
</supportedProjectTypes>
<instructions>
<_include>-osgi.bundle</_include>
</instructions>
</configuration>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
<execution>
<id>bundle-install</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
...
with bnd instructions
Web-ContextPath: my-root-http/rest/
Service-Component: *
OSGi has a part of specification called Remote Services. In very short it works in the way that you can register services with special service-properties and based on the properties technologies should pick up your service and create an endpoint from them. It is not only about REST but about any technology that handles remote calls. You may find information in the OSGi Core specification under the "Remote Services" chapter.
Well it is a specification but who implements it? Currently there are two bigger projects I tried. CXF DOSGi and Eclipse ECF. They offer several technologies that support Remote Services Specification. CXF especially upports Jax-RS based on it's implementation on both server and client side.
As I did not want to use spring specific solutions inside OSGi I did not use CXF on the end but created my own solution. It is based on Jersey and the Remote Services specification. When an OSGi Service is specified with the service.exported.interfaces=* and the service.exported.configs=org.everit.osgi.remote.jersey it will create a rest endpoint under the /rest/ path with HttpService. Your bundle does not have to be a wab it can be a simple bundle.
I must mention that if you expose your services via any of the Remote Services implementation you should take the Jax-RS annotations into an interface that is implemented by your original class and expose your service based on that interface.
Instead of #Resource and #Component annotations inside OSGi I suggest that you should use Blueprint (part of OSGi spec) that is amazingly similar to Spring. Currently Apache Aries and Gemini Blueprint implements it. With blueprint you can easily create beans and wire them to each other. If register your remote service in this way you can set any of the property with the help of blueprint (just like the property of a bean in the spring applicationcontext.xml).
You can find a sample application that I made at https://source.everit.biz/svn/everit-osgi/trunk/samples/jaxrs/ (user/passwd: guest/guest). There is a guide that explains how this samples can be started and developed at http://cookbook.everit.org
I hope the sample application helps you to get started with the Remote Services specification chapter.
To see how to use JPA and Injection (Blueprint) you should check the OSGi compendium specification for possibilities and find the implementation you like. I also made a sample project based on blueprint and hibernate-jpa that you can find as the sibling of the sample url I already provided.
Update
There is also a JAXRS extender implementation I made at https://github.com/everit-org/osgi-remote-jersey. See the README for documentation. It is different from the first in the way that this works based on whiteboard service properties.
I have experienced a similar problem with OSGi, Declarative Services and Jersey.
A resource can be annotated with #Component and #Reference annotations. This will instruct DS to create an instance of SomeResource class and to inject a valid reference into this instance when all dependecies (references) are satisfied.
The reason why your references are null is because JAX-RS implementation will create a new instance of SomeResource class for each web request. This instance of SomeResource class is not the same as the one created by DS.
I solved this problem by making reference variable static with Java static keyword:
private static SomeService service = null;
This ensured that a dependency reference is tied to a class object instead to an instance and then all instances could see the injected value.
This solution introduced a new problem. This reference must be cleared on unbind event (when service becomes unavailable) because it will not be destroyed when an instance is destroyed.
The problem would be solved when the #Path annotated type would be registered as a service itself. With DS you can than just inject other services. I faced this problem myself nearly a year ago. Thats why I wrote a small OSGi JAX-RS Connector which gives you exactly what I have described. Give it a try if you like: https://github.com/hstaudacher/osgi-jax-rs-connector

Emply EJB and Servlet

After reading about it for so long, I now have chance to get my hand dirty with EJB. I use Glassfish+Eclipse 3.7 on Ubuntu.
I first created an EJB that just returns a greeting message. Then I create the application client to access this EJB using InitialContext. This works exactly like expected.
Then, I created a servlet to access to that EJB. Neither access with #EJB nor InitialContext works.
When I use #EJB, the 404 page appear with this description: "The requested resource () is not available."
When I use InitialContent, an ClassNotFoundException is thrown. Apparently, the class loader of the servlet cannot access to the EJB class. I tried to add EJB jar file to the servlet's lib folder and I got the error message that the JNDI name already exists. Apparently, Glass Fish tries publish the EJB in the Servlet's lib folder too.
The only way to get this to work is to publish the EJB with the servlet. This way, both I can get the servlet and a stand-alone application to access to that EJB. The problem is that I need to always employ the servlet with the EJB which is not desirable since my client may not want to use web front end.
Anyway, my question is what is appropriate way to have the servlet access to the EJB employed outside its class loader without repeatedly publishing the EJB.
P.S. It is also possible that the problem might be the way Eclipse configure and employ those components.
Thank a lot for any helps.
Perhaps you need to treat the EJB component as if it were remote. And maybe it really is since you don't give a lot of detail on how you are deploying. Try the directions at http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#nonJavaEEwebcontainerRemoteEJB.
A few pointers:
you may need to put the webapp and the ejb-jar in an .ear (enterprise application) and deploy it to glassfish
you may need the remote interfaces on the classpath of the webapp (if they are not available at runtime, but they were at compile time, you can't expect it to work)
NetBeans is generally better with enterprise stuff and wizards for creating and deploying applications. Give it a try.
After try out a while, I found that I can do by referring it as "/". This even works with injection.

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.