Integrating EJB3 with Spring - java

I'm building application with EJB and Spring 3. I have three maven modules - Spring jars, EJB jar and web part. In the web part I want to call my EJB session bean. Here comes the code of it:
#Controller
public class IndexController {
#EJB
PaymentRemote paymentRemote;
}
I have also an application context file, with the content:
<jee:local-slsb id="paymentRemote" jndi-name="ejb/myBean"
business-interface="net.learntechnology.ejb.PaymentRemote"/>
and
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true"/>
In my ejb module I have an interface:
#Local
public interface PaymentRemote {
}
Unfortunately when I deploy it on JBoss as 5 i get the following error:
Error creating bean with name 'paymentRemote': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: ejb not bound.
I saw a lot of examples in net and all are configured like this. I'm stuck with it...
Could any one help me with this? I would be more than grateful!

For JBOSS the proper pattern is:
application-name/bean/remote or local

Since my comment turned out to be the answer, I'll rephrase it....
Make sure that the EJB is actually bound to JNDI under the name you're expecting. The error message suggests that it's not.
In JBoss, to the JMX Console, look for the JNDIView object, and invoke its list method. If your EJB is present on ejb/myBean, it should appear here. If not, look for its under a different name, and bind to that.

Related

Classpath scanning of dependencies

I have a 3-tier application: web-service, service-layer and domain-layer. The web service is present in a web application (WAR). The service-layer and domain-layer are two JAR projects. The dependencies are:
web-service --> service-layer --> domain-layer
In the service layer, the services are annotated with #Service. In the domain-layer, the DAOs are annotated with #Repository. The web service implementation class uses the services of the service-layer JAR, so it keeps one instance of each service which is automatically injected (#Autowired).
The dependencies are well defined in my POMs. When I deploy my WAR on Tomcat, I get the following exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.mycompany.project.services.MyService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
... 37 more
I quote from one relevant part in the Spring docs:
The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do not activate the files-only switch of
the JAR task.
I've checked and the service-layer JAR is present in the WEB-INF/lib directory.
Any idea?
Thanks
EDIT: I have only one context file which is located in the web-service layer project (WAR) under src/main/webapp/WEB-INF. In this context, I've enabled classpath scanning as follows:
<context:component-scan base-package="com.mycompany.project" />
The package com.mycompany.project is the base package of my project, under which there are the web-service (com.mycompany.project.server), service-layer (com.mycompany.project.services) and domain-layer (com.mycompany.project.domain) packages.
I've solved the issue. I don't understand why what I've done was causing such an issue. Each service implements an interface that defines its public methods. In my web service implementation class, the references to the services used the implementation classes and not the interfaces. I just changed them to use the interface, and I don't get the issue anymore. Could anyone explain me what's wrong with using the services implementation classes instead of the interfaces for the autowiring?
This is an answer for your EDIT:
The reason why referring to the interface worked but the concrete implementation failed is probably to do with the dynamic proxies that Spring creates for cases where you have your services annotated with #Transactional etc. What happens in such cases is that the type of your beans are not the implementation type anymore, but wrap around your impementation type. So when you have #Autowired by implementation type, it just cannot find it by type (which is the default).
Your fix is very appropriate, as a dynamic proxy continues to derive from the interfaces that you have defined for your implementation and so can inject by interface type - the reference that I have provided does a better job explaining this.
make sure you used <context:component-scan base-package="your.service.package"/>
check your autowired strategy is byName or byType; if byName, the Service annotation's name value should be right.
if problem still exist, check spring's log, it will print all found components' name, you could know the service is founded or not.
Can you show your component scanning configuration? If this is not set up correctly then Spring may not be discovering your service.
You want something like:
<context:component-scan base-package="your.service.package"/>
Edit:
I think the problem is that your #Service annotation is on the interface rather than implementation class.
If you annotate your service implementation then your web controller can use either:
#Autowired
private ExampleService service;
or
#Autowired
private ExampleServiceImpl service;

JBoss 5.0 EAR: Locate #Service ejb local interface from struts 1 action in nested war with jndi lookup

I have a war (using struts 1) nested in an ear with session ejbs. If I lookup normal session beans from the war with lookup("earname/beanname/local") everything works. If I lookup a #Service ejb the same way it fails from the war with a NamingException.
To make sure I was doing the lookup correctly I looked up one #Service bean from another's start() method (instead of injecting with annotations) and the jndi lookup succeeded.
What could be the cause of this behavior? I am currently stuck with JBoss 5.0.
After going through the jmx-console like Nicholas recommended I was able to track down my mistake.
It turns out my two lookups were in fact different. The war was using the service name that I wanted, everything else (which was working) was using the class name of the implementation of the #Local interface.
To further the confusion I used #Service(objectName="blah") instead of #Service(name="blah").
I am now able to successfully lookup my #Service ejbs from my war.

How are you supposed to access EJB when using Easyrest?

I have been trying to get Resteasy to work (and not it dose). However I now have another headache with accessing the EJB:s. I have tried injecting them, looking them up with jndi and most other solutions but none of them works.
I get massages like: java.lang.RuntimeException: Class is not a root resource.
Or: java.lang.IllegalArgumentException: Wrong target.
Or just: NullPointer
Using JBoss 5.1.0.GA and Resteasy 1.2.1.GA... Can't find any documentation on how this could be done. Do anybody know?
Have you seen this: EJB Integration?
Resteasy currently only has simple integration with EJBs. To make an EJB a JAX-RS resource, you must annotate an SLSB's #Remote or #Local interface with JAX-RS annotations:
Next, in RESTeasy's web.xml file you must manually register the EJB with RESTeasy using the resteasy.jndi.resources

Java EJB interface

I have been working through this tutorial. Halfway though it creates an interface and facades for an EJB. Can anyone tell me when I reference the interface using the #EJB annotation, where does it actually make the link between the interface and the actual enterprise java bean itself.
Thanks for the help.
~ Kyle.
It is AFAIK not mandated by the J2EE specification how this is actually solved or implemented by the application server. The most common solution is that the app server uses its own mapping between bean class names and JNDI names, so that depending on the bean class name, it is bound to a specific JNDI path when deploying the application and the same class name -> JNDI path conversion is used for injecting the EJB reference on the "client side".
It will be done inside the EJB container.
When you add this annotation, you'll actually be telling the IoC container of your application server which implementation of the given EJB you want.

Weblogic 10.3.1 gives 'Dependency injection failure' warning when publishing code

Weblogic 10.3.1 gives me a "Dependency injection failure" when I publish my code; the publish itself succeeds. I am working via Eclipse.
Basically I publish an ear with a web service aaa.MyWebServicePort that has a bean bbb.MyBean declared as local variable with the ejb 3.0 #EJB annotation. bbb.MyBean is also in the ear as well as a client project with the interfaces defined.
After publishing the web service works on the appserver and calls bbb.MyBean. So why the warning?
Details of the warning in the console window of Eclipse: Error creating bean with name 'aaa.MyWebServicePort': Initialization of bean failed; nested exception is [...] BeanCreationException: Dependency injection failure: can't find the bean definition about class interface bbb.MyBean; nested exception is [...] NoSuchBeanDefinitionException: No unique bean of type bbb.MyBean is defined: No beans of type bbb.MyBean;
There may be a couple of issues at work here. I'm getting a very similar error in just a straight servlet that is trying to load an ejb that isn't packaged in the same ear, I'm still trying to track that down. I also know that there is a difficulty when loading EJB v2.x that is supposed to be fixed in Weblogic 10.3.3.
If you find anything please let me know, and I'll do the same. One thing I have noticed is that if I load the EJB via initialContext.lookup, it works fine.
YMMV

Categories