EJB Injection Between EARs on the Same Server - java

I'm running into an issue trying to migrate an application from Jboss AS6 to Wildfly. The application consists of a 'Product' ear, a 'Person' ear, and a 'Common' jar containing shared interfaces and utilities. All are being deployed as modules on a Wildfly application server. I need to be able to inject a service bean defined in Person into Product. The LoginService bean is located in Person and looks like this:
#Stateless
#Remote(LoginService.class)
public class LoginServiceBean implements LoginService {
#Resource
protected SessionContext context;
}
When I build and deploy the Person ear, I get the following log for my jndi bindings:
java:global/Person/Person-ejb/LoginServiceBean!com.tura.common.service.login.LoginService
java:app/Person-ejb/LoginServiceBean!com.tura.common.service.login.LoginService
java:module/LoginServiceBean!com.tura.common.service.login.LoginService
java:jboss/exported/Person/Person-ejb/LoginServiceBean!com.tura.common.service.login.LoginService
ejb:Person/Person-ejb/LoginServiceBean!com.tura.common.service.login.LoginService
java:global/Person/Person-ejb/LoginServiceBean
java:app/Person-ejb/LoginServiceBean
java:module/LoginServiceBean
In the Product project I then have a stateless EJB bean
#Stateless(name = "ClientServiceProvider")
public class ClientServiceProviderBean implements ClientServiceProvider{
#EJB(name = "ejb:Person/Person-ejb/LoginServiceBean!com.tura.common.service.login.LoginService")
protected LoginService loginService;
}
When I try to deploy, it then fails with the error:
No EJB found with interface of type
'com.tura.common.service.login.LoginService' for binding
ejb:Person/Person-ejb/LoginServiceBean!com.tura.common.service.login.LoginService"
I've tried every binding configuration I can think of; nothing seems to work. All the documentation I can find seems to want to use a manual jndi lookup rather than the annotation. What am I doing wrong here? Is there really no way to inject services between EARs?

Related

Access Spring beans from Alfresco integration test context

Now that Alfresco integration tests of custom modules are run using Docker, I wonder how to make additional Spring beans available in this context and how to access existing Spring beans in test classes.
Until Alfresco 5.x, I used to annotate the test class with
#ContextConfiguration("classpath:alfresco/application-context.xml")
This made the Spring context available. To make Spring beans from this context available in the test class, I annotated members like this:
#Autowired
#Qualifier("authenticationComponent")
private AuthenticationComponent authenticationComponent;
In addition I was able to define additional Spring beans in src/test/resources/alfresco/extension/test-context.xml.
Is this the approach to use when writing integration tests for 6.x and Docker?
At least the annotation org.springframework.test.context.ContextConfiguration is no longer included in a module build using the Maven 4.0.0 SDK archetype.
This blog post talks about the above mentioned annotations. But the dependencies pulled in by the pom.xml created from the SDK 4 archetype don't include these annotations.
A different approach seems to be to only use
#RunWith(value = AlfrescoTestRunner.class)
on the integration test class. But how do I get the Spring beans like nodeService injected into it? And how do I declare and make available additional Spring beans which are part of my custom module and required by the integration test to succeed?
You can get the Spring context via AlfrescoTestRunner as follows:
#Before
public void setUp() {
this.nodeService = (NodeService) super.getApplicationContext().getBean("nodeService");
}
I do the same with custom beans:
super.getApplicationContext().getBean(MyType.class);
Since the integration tests run in the repository, all of the Spring context is automatically available.
Note that your test class needs to extend AbstractAlfrescoIT for this to work.
An example class may look like this:
package nl.open.mystuff;
import org.alfresco.rad.test.AbstractAlfrescoIT;
import org.alfresco.rad.test.AlfrescoTestRunner;
import org.alfresco.service.cmr.repository.NodeService;
#RunWith(value = AlfrescoTestRunner.class)
public class MyCustomIT extends AbstractAlfrescoIT {
private NodeService nodeService;
private MyType myType;
#Before
public void setUp() {
this.nodeService = (NodeService) super.getApplicationContext().getBean("NodeService");
this.myType = super.getApplicationContext().getBean(MyType.class);
}
}
In Alfresco SDK 3, you can even add your own Spring XML files under src/test/resources/alfresco/extension/*-context.xml. I imagine this still works, but I haven't tried it with SDK 4 myself.

Is it possible to have EJBs in domain1/lib using GlassFish?

I use GlassFish 4 web profile and I have the following interface and class.
#Local
public interface SomeService {
...
}
#Singleton
public class SomeServiceBean implements SomeService {
...
}
When I put interface and class in .war archive (that is in domain1/autodeplay) everything works fine. However, when I put interface and class in separate .jar archive (that is in domain1/lib) then deploying war application I get:
java.lang.RuntimeException: Cannot resolve reference Local ejb-ref name=com.temp.MyServlet/someService,Local 3.x interface =com.temp.SomeService,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session
at com.sun.enterprise.deployment.util.ComponentValidator.accept(ComponentValidator.java:374) ~[dol.jar:na]
at com.sun.enterprise.deployment.util.DefaultDOLVisitor.accept(DefaultDOLVisitor.java:78) ~[dol.jar:na]
at com.sun.enterprise.deployment.util.ComponentValidator.accept(ComponentValidator.java:123) ~[dol.jar:na]
at com.sun.enterprise.deployment.util.ApplicationValidator.accept(ApplicationValidator.java:152) ~[dol.jar:n
...
I don't use any xml descriptors. So, is it possible to have EJBs in domain1/lib and if yes, how to make EJB container find them? P.S. I tried in GF 4 full - result is the same.
EJBs cannot be added as a library to GlassFish, libraries are just added to the classpath and any annotations on them are ignored and they do not go through the EJB container. If you do want your EJBs as a seperate JAR, they can be deployed just like a WAR or EAR file.
In the Glassfish reference manual for the add-library command it says that it "adds the library to the class loader directory", while for the deploy command it says that "Applications can be...EJB modules".
Also by looking at the source code for Glassfish it can be worked out that all libraries are simply added to the Classloader either at launch (See here and here) or if in applibs then when the application is deployed (See here).

How to access application scoped cdi bean packed as jboss shared library

I have to use an application scoped cdi bean present in jboss shared libraries in my ear application.
Example:
jboss\modules\com\test\test.jar
In test.jar I have one application scoped bean
#ApplicationScoped
public class Test {
#Inject
SomeClass someClass;
#PostConstructor
public void init() {
someClass.doSomething();
}
public void testMethod() {
}
}
myapp.ear → ejb.jar
In ejb.jar I have one class which initializes Test application scoped bean.
public class Another {
#Inject
Test test;
public void myMethod() {
test.testMethod();
}
}
When I test this example, I'll get null pointer exception as I'm trying to inject application scoped bean which is out side an ear application.
Note: I cannot have test.jar in my ear lib directory, as per my requirement it will be delivered as jboss shared library.
Any ideas how to access application scoped bean?
Add beans.xml to META-INF directory of your test.jar. In this case container will scan test.jar file for CDI beans.
This is also strange that you get NPE. You would get "unsatisfied dependencies" if injected bean was not found. Probably you instantiate Test bean incorrectly. For example, via the New operator.

Two differents projects in eclipse: (JPA & EJB) in a EAR Project (problems with CDI)

Hy guys, first: My english is not good, but.. come on:
I have two projects in eclipse:
JPA (with models & dao's)
EJB (with my web services)
and an EAR Project (JPA + EJB). My setup: JBoss 7.1 AS
My problem:
#Stateless
#WebService --> THIS IS IN EBJ PROJECT
public class PessoaFisicaWS implements Service {
#EJB
private PessoaFisicaDAO dao;
}
this is my DAO Impl
#Stateless ->> THIS IS IN MY JPA PROJECT
public class JPAPessoaFisicaDAO extends JPAAbstractDAO<PessoaFisicaBean>
implements PessoaFisicaDAO {
public PessoaFisicaBean getPessoaFisicaByCPF(String cpf) {
TypedQuery<PessoaFisicaBean> query = manager.createQuery(
"SELECT p from PessoaFisicaBean p where p.cpf = :cpf",
PessoaFisicaBean.class);
query.setParameter("cpf", cpf);
return query.getSingleResult();
}
// with others impl
}
OK
EJB Project add JPA Project in your classpath. OK
NO ERRORS. BUT in deploy:
Caused by: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS014544: No EJB found with interface of type 'br.com.processo.dao.PessoaFisicaDAO' for binding pacote.PessoaFisicaWS/dao
any idea?
EDIT:
When i add (DAO's and your impl) in my EJB Project (same package of WebService) ITS WORKS.
But i need separate in two projects.
Try to remove this annotation #EJB from dao because this is not an EJB.
Each module has its own classloader, so that the visibility of the class is limited to each module. You need create a jar with the interfaces and put in the lib directory of the EAR. See more in Class Loading in AS7, e.g.:
You need create a standard java project for store the business interfaces. The deployment assembly:
In the project explorere view you see:
It is pretty simple. The error is telling you to reference the Interface not the Implementation.
So make sure that "PessoaFisicaDAO" is an Interface with the #Remote or #LocalBean annotation
#EJB
private PessoaFisicaDAO dao;

Problem deploying scheduled EJB to Glassfish server

I have a weird (?) problem with an EJB I want to deploy to my Glassfish 3.1 application server.
I have this bean, which should be executed continuously in Glassfish using the #Schedule annotation. This worked fine for me until I added some code to the EJB accessing a database.
#Stateless
public class MyBean implements MyBeanLocal {
#Schedule(second = "*", minute = "*", hour = "*")
public void initiateProcess() {
MyCoordinator mc = new MyCoordinatorImpl();
List<Entity> entities = mc.methodAccessingDB();
}
}
This is my EJB, which is executed every second. How I said above, I can deploy this EJB and it executed successfully, if I don't call ac.methodAccessingDB().
This means, that I can't even deploy it to Glassfish. Glassfish tells me
Invalid ejb 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..
Please see server.log for more details.
If I just write List<Entity> entities = null; instead of List<Entity> entities = ac.methodAccessingDB(); I can deploy it and it runs fine.
OK, now I have found the solution for this problem. The EJB couldn't find the classes on the deployed version. The solution was to pack everything into an ear project. I am using maven, so I created in the end 3 projects.
one for the EJB <packaging>ejb</packaging>
one for the EAR <packaging>ear</packaging>
and a third parent project, which integrates the both other projects as <module>.
I then deployed the packed ear to Glassfish and the timer started and everything was there.

Categories