EJB 3.1 problems - java

I try to deploy a jboss5 bean project bundle on a jboss7 server. An other developer already made some changes that the code can work on jboss7, like to place a jboss-deployment-structure.xml into the project.
I created two beans, one in project A (BeanA) and one in project B (BeanB).
BeanA has to lookup for BeanB. I always get "No EJB found with interface of type 'de.foo.soa.foobar.al.BeanB' for binding de.foo.soa.foobar.ba.ProjectB/BeanB.
Bean B:
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
#Stateless
#LocalBean
public class NumSrvLocalBean {
public String testNumSrv() {
return "numsrv works";
}
}
Bean A does:
#EJB private NumSrvLocalBean numSrvLocalBean;
private String numSrvLocalBean_path = "java:module/NumSrvLocalBean!de.foo.soa.foobar.al.NumSrvLocalBean";
ctx = new InitialContext();
numSrvLocalBean = (NumSrvLocalBean) ctx.lookup(numSrvLocalBean_path);
I also added the right dependency to the jboss-deployment-structure.xml:
<module name="deployment.ProjectB.jar" export="true"/>
So evertything is fine for my understanding but I always get this exception. I created my own project, lets call it project X. There I can lookup for any Bean I want to from all other projects (about 15). I cant inject in project A any bean outside from project A. But I can inject beans inside the project. So there must be something that blocks the beans inside the project.
I've got this files in project A:
jboss.xml
jboss-deployment-structure.xml
MANIFEST.MF (standard, not filled)
persistence.xml
seam.properties
ProjectA.properties (contains an wsdlUrl because this project was also configured as XML-RPC project)
I look forward four your ideas,
greetings.

I solved this problem by using EJB(mappedName="java:global/....").
I already tried EJB(mappedName=className.JNDI_NAME) but this didnt worked. We used Interfaces in JBoss 5, where we defined the JNDI name like
#Local
public interface ClassNameLocal extends ClassNameInterface {
/** Name im JNDI (Java Naming and Directory Interface) */
public final static String JNDI_NAME = "foo/bar/and/so/on/ClassName/local";
}
This seems not to work anymore. I needed to use the full path.

Related

EJBConfigurationException on Websphere Liberty Base 17

I have to migrate a software project from Websphere Application Server v8 (WAS8) to Webphere Liberty Base v17 (WL17) and ran into troubles with the EJB's. E.g. there is the following EJB:
#Stateless
#Local(MyUserServiceLocal.class)
public class MyUserServiceBean implements MyUserServiceLocal {
#EJB
private OtherServiceLocal otherServiceLocal;
#Resource
private SessionContext context;
public MyUserServiceBean() {
}
public String getUserEmail() {...}
public String getUserDataId() throws ServiceException {...}
...
}
With the corresponding local interface:
#Local
public interface MyUserServiceLocal {
public String getUserEmail();
public String getUserDataId() throws ServiceException;
...
}
There are a lot more EJB's following a similar implementation scheme.
The project builds fine, all facets in all Eclipse projects are set correctly and maven creates a fresh and deployble EAR file. But when I visit the applications default page the following nested exception is thrown: The MyUserServiceBean bean class for the MyApplication#MyUserServiceEjb.jar#MyUserServiceBean bean does not have a public constructor that does not take parameters.
I currently can not imagine why this exception is thrown by WL17. The feature configuration of my WL looks like this:
<featureManager>
<feature>appSecurity-2.0</feature>
<feature>cdi-1.2</feature>
<feature>distributedMap-1.0</feature>
<feature>ejbLite-3.2</feature>
<feature>ejb-3.2</feature>
<feature>jacc-1.5</feature>
<feature>jaxrs-2.0</feature>
<feature>jaxws-2.2</feature>
<feature>jca-1.7</feature>
<feature>jdbc-4.1</feature>
<feature>jndi-1.0</feature>
<feature>jpa-2.1</feature>
<feature>jsf-2.2</feature>
<feature>jsp-2.3</feature>
<feature>ldapRegistry-3.0</feature>
<feature>mdb-3.2</feature>
<feature>servlet-3.1</feature>
<feature>ssl-1.0</feature>
<feature>webCache-1.0</feature>
<feature>wmqJmsClient-2.0</feature>
</featureManager>
I is the same when I do not load the mdb or the ejb feature. Is there any idea how to solve this problem? I have googled a lot and reade half of the internet but didn't get an answer or an idea how to solve this problem.
I found the problem of the EJB. One of the interface methods was declared to throw a javax.xml.rpc.ServiceException. I do not understand why this should be a problem, but after removing the throws declaration in the interface and the implementation class WL 17 was able to initialize the bean correctly.

Referencing EJB Local home from a POJO class of a separate web application

I am trying to port 2 EJB modules in my application from EJB2.1 to EJB3.0. I am using the Eclipse Kepler IDE and regenerated the session beans using an EJB3.0 configuration. I am not using an ejb-jar.xml because in EJB 3.0 that is supposed to be redundant. I have instead used annotations for marking my bean as Stateless and specifying the Local and Local Home Interfaces. I have still kept the Local Home interface since I wanted the basic structure of my project to be similar to what it was in EJB2.1. I have also done away with the xml bindings for the EJB while migrating.
We are using a WAS 7 application server for deployment and while the EJB is getting successfully deployed without errors, I am getting a naming Exception while looking up my Local Home interface from a separate POJO class of a different web application it is required in. I basically want to call the create() method of the Local Home interface after referencing the EJB Local Home. Adding code samples below:
Session Bean:
#Stateless
#Local(AccessLDAPSessionLocal.class)
#LocalHome(AccessLDAPSessionLocalHome.class)
public class AccessLDAPSessionBean implements AccessLDAPSessionLocal {
//Business Logic
}
Local Interface:
public interface AccessLDAPSessionLocal {
//business Interface
}
Local Home Interface:
public interface AccessLDAPSessionLocalHome extends EJBLocalHome {
public AccessLDAPSessionLocal create() throws CreateException;
}
Pojo class referencing the Local Home interface:
public static AccessLDAPSessionLocal getAccessLDAPSessionBean() throws NamingException, CreateException {
if (accessLDAPSessionBean == null) {
InitialContext context = new InitialContext();
Object obj = context.lookup("java:global/AccessLDAP/AccessLDAPSessionBean!com.ibm.asset.hrportal.core.ejb.ldap.AccessLDAPSessionLocalHome");
accessLDAPSessionBean = ((AccessLDAPSessionLocalHome) obj).create();
}
return accessLDAPSessionBean;
}
Also my Local and Local Home interfaces are inside my EJB client which I use as a jar file, while my Session Bean is inside the actual EJB which is used as an EAR.
Following is the error I am getting:
NamingException::javax.naming.NameNotFoundException: Name global not found in context "java:".
Am I missing some configuration resulting in the failure of JNDI lookup? Any help would be gratefully appreciated. Thanks in advance.
WebSphere Application Server 7.0 is only an implementation of EJB 3.0, but the java:global namespace wasn't added until EJB 3.1, which wasn't implemented in WebSphere Application Server until 8.0. As with all EJB 3.0 implementations, you will need to lookup a vendor-specific binding name. You can find the WebSphere Application Server binding name by looking at the CNTR0167I messages in SystemOut.log. See the EJB 3.0 application bindings overview topic in the Knowledge Center if you would like to customize this binding name.
Regardless, it is not a best practice to directly lookup EJBs by their binding name. Instead, you should use an EJB reference. In EJB 3.0, that means using an annotation like this in an EE managed object (such as a servlet or another EJB):
#EJB
private AccessLDAPSessionLocalHome home;
In this case, the EJB container is required to find a target EJB within the same application that contains the EJB reference, so you do not need to explicitly configure a target binding name for the EJB reference.
If you need to access the EJB reference from a utility class rather than an EE managed class, then declare the EJB reference with a name on a managed class (such as a servlet or another EJB), and look it up from the utility class:
#EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class)
public class MyServlet { ... }
public class MyUtility {
...
InitialContext context = new InitialContext();
Object obj = context.lookup("java:comp/env/ejb/accessHome");
...
}
You can configure multiple such EJB references on the same managed EE class using the #EJBs annotation:
#EJBs({
#EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class),
#EJB(name = "ejb/other" beanInterface = Other.class)
})
public class MyServlet { ... }
If your EJB is packaged in a separate EAR, then note that this is not a portable configuration. See the "Local client views" section of the EJB modules topic in the Knowledge Center. Additionally, you will need to explicitly configure a binding name for the EJB reference.
I think the way you are looking up the ejb is not correct. The JNDI name would be something like "java:comp/env/". ejb-ref-name would be part of your web.xml
Also, you will need to give providerURL and factoryName to the context object before doing the lookup.

Root resource from other .jar file cannot be looked up in JAX-RS application

I am trying to build an application ear file with the following structure:
app.ear
--> lib
-- app-domain.jar
-- app-api.jar
-- app-common.jar
...
--> META-INF
-- application.xml
-- glassfish-application.xml
-- MANIFEST.MF
-- app-ejb.jar
-- app-rs.war
The app-api.jar file contains my remote interfaces like
#Remote
public interface LanguageService {
/**
* #return all languages known to the system
*/
List<Language> loadLanguages();
The implementation is contained in the app-ejb.jar file and looks like this:
#Stateless
#Remote(LanguageService.class)
#Path("/language")
public class LanguageServiceImpl extends ValidatingService implements LanguageService {
#PersistenceContext(unitName = "kcalculator")
EntityManager em;
#GET
#Produces("application/json")
#Override
public List<Language> loadLanguages() {
CriteriaQuery<Language> query = createLoadLanguageQuery();
return em.createQuery(query).getResultList();
}
And finally I want to provide this as an JAX-RS web service and thus have my implementation of the javax.rs.Application class in the app-rs.war file, which looks like this:
#ApplicationPath("/resources")
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(LanguageServiceImpl.class);
return s;
}
This deploys without any problem, the application class is also detected. However, when i finally access the web service an internal server error occurs due to a NPE.
The LanguageServiceImpl cannot be looked up, the log contains the following entry:
Caused by: javax.naming.NameNotFoundException: No object bound to name java:module/LanguageServiceImpl!com.kcalculator.ejb.LanguageServiceImpl
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:741)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:715)
at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:167)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:471)
... 63 more
Hence the file is considered a Pojo, and so the reference to the entity manager is not initialized, which finally results in the Nullpointer exception.
I am kinda stuck, as annotating the bean class and giving it a mapped name is not working. Putting my application class into the ejb.jar file does not solve the problem either.
Can anyone point out what i am missing here?
Additional comment:
What I found out in the meantime: If I add a stateless session bean to my app-rs.war file and register it in MyApplication, it works without any problem. There injecting the LanguageService works, too. So it seems the problem is related to the fact that the service implementing bean class is located in another artifact.
The problem could be that you have an EJB with a remote interface.
JAX-RS 1.1 states in 6.2 that JAX-RS annotations only need to be supported on no-interface beans and local interfaces:
JAX-RS annotations MAY be applied to a bean’s local interface or directly to a no-interface bean.
As indicated in one of the previous comments, a working solution was found by moving the session beans to the web archive as well. Thus the separation between the ejb .jar file and the disclosing web service containing project is gone, however it seems rational to have the services in the artifact that is also supposed to provide the web services.
Thanks for the hints, however it is still not clear to me (according to the specification) why the initially described approach should not be feasible (but i realized it isn't...).

Why is Spring not wiring my #Autowired members in a dependent jar?

I'm building a Google App Engine app using Spring 3.1 and am having a problem getting members in one of my jars wired.
I have three projects:
server
server.model
server.persistence
I have an ant build script so that when my workspace builds, it creates jars for server.model and server.persistence, and puts them in the correct lib directory for the server project.
In server, I can autowire things from both server.model and server.persistence, but in server.model my server.persistence beans aren't getting wired even though they're the exact same as in server.
snippet from my servlet application config:
<context:component-scan base-package="com.impersonal.server"/>
<bean autowire="byType" id="appEngineDataStore" class="com.impersonal.server.persistance.AppEngineDataStore"/>
<bean autowire="byType" id="userList" class="com.impersonal.server.model.UserList"/>
I have the following code in both the server project and the server.model project, and only the server one gets fulfilled. Here's the one failing:
package com.impersonal.server.model;
import java.util.ArrayList;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import com.impersonal.server.persistance.AppEngineDataStore;
import com.impersonal.server.persistance.IDataStore;
public class UserList extends ArrayList<User>
{
private UserList(){}
//this is always null, but the same line in a class in the other project works
private #Autowired AppEngineDataStore _dataStore;
public UserList(UUID userId, String tempId)
{
String poo = "poo";
poo.concat("foo ");
int i = 3;
}
}
Edit:
Just did a test in the server.model project trying to #Autowired something that I don't have defined as a bean in my application config, and didn't get any errors. I should have got a 'no such bean found' error like I do if I do the same thing for the server project.
Any ideas why?
I was instantiating my objects incorrectly. For framework objects and such like MVC controllers, you don't need to do anything to get your #Autowired members wired.
For objects I was creating on the fly, I wasn't going through the IOC container, that's why their dependencies weren't being fulfilled.
<context:component-scan/> tag searches for annotated classes.
If you are going to autowire class using #Autowire annotation, Autowiring class should be annotated with one of stereotype annotation (#Component,#Controller,#Service,#Repository). Spring resolves first annotation configuration and then xml configuration. This is written in spring doc as
Annotation injection is performed before XML injection, thus the latter configuration will override the former for properties wired through both approaches.
Check proof on spring doc.
So what you need to do is add annotations for classes from server project as well as server.model. Same in case of your third project server.persistence. Add annotations according to layers or functionality.
Try:
#Autowired(required = true)
private AppEngineDataStore _dataStore;
Instead of:
private #Autowired AppEngineDataStore _dataStore;
EDIT 1:
While using the autowire above, in your spring xml, try:
<bean id="appEngineDataStore" class="com.impersonal.server.persistance.AppEngineDataStore" scope="prototype"></bean>
Instead of:
<bean autowire="byType" id="appEngineDataStore" class="com.impersonal.server.persistance.AppEngineDataStore"/>
autowire in xml means slightly different thing. Instead of defining your bean in xml, you can annotate it as #Service, it will be discovered by the component-scan and the #Autowired will work.
In your xml configuration, use autowire-candidate property
<bean autowire="byType" id="appEngineDataStore" class="com.impersonal.server.persistance.AppEngineDataStore" autowire-candidate="true" />

Exclude/remove services from Dependency Indejection in JBoss

We currently have a project that consists of multiple applications as well as a base library.
Both, the applications as well as the base library contain stateless EJBs and each application might introduce an EJB that inherits from a base library EJBand thus implements the same interface.
A short example:
In the base library we have:
#Stateless
#Local( IUserService.class )
public UserServiceBean implements IUserService {
public void login(String user, String password) {...}
}
In the application we need to override login(...) and thus we have:
#Stateless
#Local( { ISpecificUserService.class, IUserService.class } )
public SpecificUserServiceBean extends UserServiceBean implements ISpecificUserService {
public void login(String user, String password) { ... } //override
}
If I now have another EJB in the application that needs to have a reference to SpecificUserServiceBean I'd do #EJB ISpecificUserService userService;.
However, if there is an EJB in the base library, it would contain #EJB IUserService userService; and here's the problem:
We need to get the specific service in the application be injected in the base library EJB. However, there are two EJBs registered for the same local interface, which means that the container might return the base EJB or the specific EJB.
You could say "Don't add the base library jar as a module in application.xml" but that's not possible right now, since it contains other EJBs that need to be deployed. We could move the EJBs to be overridden to a different jar but since almost every EJB might be overridden, depending on the application, we'd end up with a jar per EJB.
Thus, I'd like to exclude or remove the base EJB from the dependency injection container if there exists a specific override. Since I know that at deploy time, I could also use a configuration file to tell the container not to load a specific EJB class.
I might add a service that modifies the container afterwards but that would be my last resort.
Do you have any ideas on what we could do?
Thanks in advance.
Btw, we're working on JBoss 4.2.3 with EJB 3.0.
The problem is that you're wiring your app partially in the base lib which is bad since you can't override this wiring.
So the solution is to remove #Stateless #Local( IUserService.class ) from UserServiceBean in your base lib; the base lib just provides default implementations for the beans but it must not wire them.
In your apps, you need this code:
#Stateless
#Local( IUserService.class )
public AppUserServiceBean extends UserServiceBean {}
to create the wiring. Move all those beans into a special package which you can copy into each app so you get the default wiring for everything.

Categories