CDI and EJB mix with glassfish 3.1 - java

I have two application deployed on glassfish - application A and B.
Both are deployed as war package, application B uses some components from application A.
Now in application A I have an interface:
public interface BusinessInterface() extends SomeOtherInterface {
void someAction();
}
I have 3 implementations of this interface - two in application A, one in application B: BusinessInterfaceA1, BusinessInterfaceA2, BusinessInterfaceB
As long as all of them are CDIBeans, everything is fine - I'm using custom #Qualifier annotations (#BusinessInterfaceA1, #BusinessInterfaceA2) and #Default annotation for B's implementation to distinguish them.
But now I need both application's A implementations to be Stateful EJBs and this is where it becomes funny.
When I just add #Statefull annotation on both implementations, a I got something like this:
javax.servlet.ServletException: org.jboss.weld.exceptions.WeldException: WELD-000049
details:
java.lang.IllegalStateException: Unable to convert ejbRef for ejb BusinessInterfaceA1 to a business object of type interface SomeOtherInterface
How can I fix it? I need all implementations to be avaliable in a way I could inject them like
#Inject #SomeAnnotation private BusinessInterface businessInterface;

It is bug in Glassfish 3.1. The workaround is, to mark implementation with all required interfaces, e.g.:
#Statefull/#Stateless
public class BusinessInterfaceImpl implements BusinessInterface, SomeOtherInterface {
// implementation
}
Even BusinessInterface extends SomeOtherInterface, and from Java specs its useless to do that, but as a workaround for that bug it works.
Another solution is to use Glassfish 4.0

Related

Inject multiple remote EJBs in bean

In Java EE, if I have an interface:
#Remote
public interface MetaService {
ServiceData get();
}
And I have, in an ear 2 implementations:
#Stateless
public class Service1MetaService implements Calculator {
#Override
public ServiceData get() {...}
}
#Stateless
public class Service2MetaService implements Calculator {
#Override
public ServiceData get() {...}
}
I can create a bean, where:
#Stateless
public class View {
#Inject
private Instance<MetaService> metaServices;
...
}
And in View, the field metaServices will have the 2 implementations of MetaService.
I'd like similar functionality with remote beans.
So let's say, I have the above interface and implementations, but the packaging is different.
In base.jar I have the MetaService interface. This is packaged will all the subsequent applications mentioned below.
In a.ear I have the Service1MetaService implementation, while in b.ear I have the Service2MetaService implementation and in c.war I have the View class, which would like to use these implementations.
But as you would expect, the injected Instance is empty (not null tho). Is there a way to find the remote bean references in my injected Instance instance, even though these implementations are in separate applications?
One important thing is that in the View class I don't know and don't care about the number of these implementations, nor the names of the applications they are deployed in. So there is no way for me to use specific JNDI strings to get these references.
P.S.: Should I try and use technologies like JMS instead? So that I call the method add on a JMS proxy, which sends out the requests and waits for answers from all the applications that implement said interface?
P.S.: To clarify, the reason I need this is actually so that I can get data of running services on my application server(s). I updated the example interface and implementations, so that it's more clear. Also, it would be nice, if I could get these metadata synchronously, so JMS is not neccessarily prefered, however I can probably make it work.
I managed to convince myself to move away from remote EJBs. Well, it was also thanks to #chrylis-onstrike- as well, however, I'll opt for using JMS for this purpose.
The reason is that I can broadcast a request for the different services I need data from on-demand, enabling me to check for new services going online, or services failing.
Thanks to everyone who spent time trying to help me out.

Inject remote ejb glassfish 4 with #producer error WELD-000044 Unable to obtain instance from null

Well, I've got some problem injecting a remote stateless EJB into another stateless EJB using a producer with Glassfish 4.0 build 89 (development environment is NetBeans 7.0).I will use a simplified naming for this purpose but my dev structure is roughly the same, that is:
ProjectA (Enterprise Application - the one used by clients)
ProjectA-ejb
ProjectA-war
lib/ProjectB-ejbClient.jar
lib/ProjectB-jpa.jar
ProjectB (Enterprise Application - behind the curtains)
ProjectB-ejb (Contains remote ejb impl)
ProjectB-ejbClient (Java class library)
Contains remote interfaces, producer, qualifier and META-INF/beans.xml
ProjectB-jpa (java class library)
Contains entites and META-INF/persistence.xml
ProjectB contains some authorization/management beans that will be used by many other projects (even on other servers) so they are remote. Later I will add a management webapp to it, so this is why it's an enterprise app and not a simple ejb project.
ProjectA instead is a complete enterprise project with ejb+webapp (and I could later add other enteprise projects ProjectC, D, etc) that uses ProjectB services.
Inside ProjectB-jpa are stored entites shared between management project (ProjectB) and single webapps (ProjectA and others).
Inside ProjectB-ejbClient class library I've writter the qualifier as this:
#Qualifier
#Target({TYPE, METHOD, FIELD, PARAMETER})
#Retention(RUNTIME)
#Documented
public #interface RemoteManagement {
}
and a bean factory producer as this:
public class ManagementBeanFactory {
#Produces
#RemoteManagement
#EJB(lookup = "java:global/ProjectB/ProjectB-ejb/Management!it.mgmnt.ejb.ManagementRemote")
private ManagementRemote managementRemote;
}
The beans.xml file is a plain JavaEE 7 template-like with attributes version="1.1" bean-discovery-mode="all" declared (I took it from Oracle tutorial).
Now, in ProjectA-ejb I have something like this:
#Stateless
#LocalBean
public class AccessControl {
public final static String APPLICATION_CODE = "GDS";
#Inject
#RemoteManagement
//#EJB(lookup = "java:global/ProjectB/ProjectB-ejb/Management!it.mgmnt.ejb.ManagementRemote")
private ManagementRemote mr;
public String performLogin(final String username, final String password) {
String uid = mr.authenticate(username, password, APPLICATION_CODE);
return uid;
}
//...
}
Projects are both deployed without any problem but when performLogin is called from the web tier I got a javax.ejb.EJBException with root cause org.jboss.weld.exceptions.NullInstanceException: WELD-000044 Unable to obtain instance from null.
I've debugged step-by-step and I found that AccessControl.mr is a reference to the remote bean and it's not null, so producer is generating a proxy to make the call.
If I swap #Inject #RemoteManagement annotatin with commented one #EJB(lookup = "...") everything works flawlessly.
I suspect that Weld is creating a proxy on AccessControl.mr property to the ManagementBeanFactory.managementRemote property that, I think, is null.
With debugger I discovered that the "toString()" references (printed on AccessControl.mr) are completely different between #Inject and #EJB and seems that #EJB has different "type" of generated proxy.
The strange thing is that I used to do the same thing with JBOSS AS 7.1.1Final using JavaEE 6 beans.xml (has different namespaces, etc) and it worked like a charm.
I don't know if I missed something in the producer/qualifier or if something has changed from JavaEE 6 to 7 (needed because I use a lot of stateless JSF views and #ViewScoped beans) on this field...or even if it's a Glassfish/Weld flaw (as I suspect).
I don't want to use Wildfly AS before it goes final and I would try to keep development and runtime in sync (same appserver) to have a more predictable environment.
If you even find errors or have suggestions in project structure/organization, please let me know. I'm glad to receive hint to get better project style.
Thank you for your help.

Ejb returns java.lang.NullPointerException

I am newbie in cdi and these are my first steps.
I have a bean in ejb module:
#Stateless
public class TestBean {
public String getIt(){
return "test";
}
}
I have a POJO in war module (I tried with #EJB and #Inject - same result)
public class SaveAction extends Action{
#EJB
private TestBean bean;
#Override
public void execute(){
....
String test = bean.getIt(); //HERE I GET java.lang.NullPointerException
...
}
}
Both war and ejb are inside ear. In log I see
EJB5181:Portable JNDI names for EJB TestBean:
[java:global/example.com/my-ejb/TestBean!com.example.TestBean,
java:global/example.com/my-ejb/TestBean]]]
From that I conclude that bean is initialized - but I can't find it. What am I doing wrong?
CDI and other dependency injection containers don't use magic! It's just ordinary java code that cannot do more or less than any other java code written anywhere. So it is impossible for a framework to do injection when an object is instantiated directly via new:
SaveAction action = new SaveAction();
// don't expect any injection has happened - it can't! no magic!
// action.bean is still null here!
The framework does not have any idea that an object like SaveAction has been instantiated. (Therefore it would be necessary to somehow inform the framework about the newly created object - but neither the constructor nor the 'new' statement do this! Just think one minute about how you would write such a framework code! It's not possible!* ).
To make injection work, the object must be created by the container instead! Otherwise it is NOT managed! (See also chapter 3.7 of the Web Beans specification (JSR 299)).
The best way to do this is to let the container inject the object into another already managed bean. It seems this just deferes the problem, but there are some already managed beans in your application, like the servlet!
Suggestion: Make your SaveAction CDI aware (e.g. annotate it with #Default) and let it be injected into your servlet!
Tutorials:
http://middlewaremagic.com/jboss/?p=1063
http://hudson.jboss.org/jenkins/job/JBoss-AS7-Docs/lastSuccessfulBuild/artifact/guides/developer-getting-started-guide/target/docbook/publish/en-US/html/helloworld.html
*) In theory it should be possible using aspect oriented programming or instrumentation to manipulate the constructors of beans to notify the container if they are invoked. But that's a very complex concept with many unsolved issues I think.

How to inject EJB Bean in different modul in Stripes ActionBean method?

Im writing JavaEE application, which contains of three modules.
In web module I need to inject ejb bean (in Stripes action bean method), which is located in ejb module.
So i followed this tutorial
http://www.stripesframework.org/display/stripes/Stripes+Injection+Enricher
My code goes like this>
#EJB
private CustomerServiceLocal customerService; //service layer for customer
and after deploying on GlassFish it returns following exception>
No EJB found in JNDI, tried the following names:
list of JNDI that it tried.
The bean is declared as follows>
#Stateless
#Local(value=CustomerServiceLocal.class)
#LocalBean
public class CustomerService implements CustomerServiceLocal {
interface>
#Local
public interface CustomerServiceLocal
I dont know what code could be relevant, so if I missed something just tell me what should I copied here.
So do you have any idea how to solve it ? How to set EJB Bean in different module in Stripes ActionBean method ?
It seems that stripes injection enricher is somehow wrongly configurated.
The problem is I need that service layer make work, since it is responsible for work with DB, and without it, I can just work with temporal local objects, which is useless.
Best regards,
OSiRiS

#Inject, #EJB, #Local, #Remote, #LocalBean, etc... : confused?

I have the following configuration:
1 EAR on one GF containing 2 EJB-JARs with EJB components.
1 WAR on another Glassfish server (=> other JVM) containing web components accessing the EJB components.
I have 2 EJB business services in each EJB-JAR of my EAR, and they are all developped like this:
#Remote
public interface ServiceAItf {
...
}
#Stateless
#Local
public class ServiceAImpl implements ServiceAItf {
...
}
In my WAR, I access the EJB components via an explicit "InitialContext.lookup" on the remote interface.
In my EAR, I am quite confused about the best practice for injection, in terms of performance, architecture, and so on...
I have the following questions:
As you can see, I have declared the annotation "#Local" on the service implementation without defining the local interface. Is it correct? At least I have no error at deployment. But maybe I should use the "#LocalBean" annotation instead? I suppose that the "#LocalBean" annotation simply allows to invoke the implementation directly as a "Local" EJB, but you have to use the implementation in your code like this:
#Stateless
#Local
public class ServiceBImpl implements ServiceBItf {
#EJB
private ServiceAImpl serviceA;
...
}
What is the best way to inject one EJB into another one?
It works like this:
#Stateless
#Local
public class ServiceBImpl implements ServiceBItf {
#EJB
private ServiceAItf serviceA;
...
}
But from what I noticed, the "serviceA" injected is the remote proxy, while it is in the same JVM within the same EAR file. So I suppose that there will be an impact on the performance. That's why I have tried to inject the service like this:
#Stateless
#Local
public class ServiceBImpl implements ServiceBItf {
#Inject
private ServiceAItf serviceA;
...
}
But it doesn't work in GF, I have the following exception:
WELD-001408 Unsatisfied dependencies for type [...] ...
I then tried to create a local interface, and the injection via the annotation "#Inject" works when both services
Even if I create a local interface like this, the service is not injected via the annotation "#Inject" but is null:
#Local
public interface ServiceALocalItf {
...
}
I read a lot of articles where it is highly recommended to use "#Inject" instead of "#EJB" when it is for a local invocation. That leads me to the following question: in which case the "#Local" EJB invocation is recommended (or simply used)?
After all this analysis, I come to the following conclusion:
For each service, I create a "#Local" and a "#Remote" interface.
From WAR to EJB-JAR of EAR, make a JNDI lookup to the remote interface.
From EJB-JAR to EJB-JAR, make an injection via "#EJB" to the local interface.
For two services within the same EJB-JAR, make an injection via "#Inject" to the local interface.
What do you think about it? Is it correct?
As you can see, I have declared the annotation "#Local" on the service
implementation without defining the local interface. Is it correct?
With EJB 3.1, the requirement for local interfaces was dropped. No need to write them unless you explicitly need them.
What is the best way to inject one EJB into another one?
Couple of things to write here:
With Java EE 6, Java Enterprise has changed. A new JSR defines a so-called managed bean (don't confuse with JSF managed beans) as a sort of minimum component that can still benefit from the container in terms of dependency injection and lifecycle management. This means: If you have a component and "just" want to use DI and let the container control its lifecycle, you do not need to use EJBs for it. You'll end up using EJBs if - and only if - you explicitly need EJB functionality like transaction handling, pooling, passivation and clustering.
This makes the answer to your question come in three parts:
Use #Inject over #EJB, the concept of CDI (a) works for all managed
beans (this includes EJBs) and (b) is stateful and therefore far
superior over pure #EJB DI
Are you sure that you need EJBs for your
components?
It's definitely worthwhile to have a look at the CDI
documentation
#Inject annotation is used for java beans(POJOs) while #EJB annotation is used for enterprise java beans. When a container inject an ejb provided by #EJB annotation to another bean it also controls that ejb's lifecycle, performs pooling for stateless beans and so on(when bean which is going to be injected is not deployed the reference will be null). If you use #Inject annotation CDI mechanism simply find and create an instance of injected resource like with new operator(if the implementation of interface which is going to be injected doesn't exist the reference will be null). You can use qualifiers with #Inject annotation to choose different implementation of injected interface.

Categories

Resources