We got Java EE 7 project with the following structure:
app.ear
META-INF
application.xml
lib
framework.jar
webapp.war
core.jar
Framework.jar is our framework that uses some kind of command pattern.
This is how it works. Each command has it's own ejb attached to it that does all the business logic. This command ejb extends CommandEJB class that have an execute method.
For example, this is an example of a command ejb:
public class cmdCreateBookEJB<T extends cmdCreateBook> extends CommandEJB<T> {
#Override
public void execute() {
//do something
}
}
And in our framework, we also have CommandExecutorEJB that sets the appropriate ejb for the command and execute it.
Example:
CmdCreateBook cmdCreateBook = new cmdCreateBook();
cmdCreateBook.setEjb(cmdCreateBookEJB.class.getSimpleName());
commandExecutorEJB.execute(cmdCreateBook);
The problem is our framework, specifically CommandExecutorEJB(that is packed in framework.jar inside lib folder) needs to know about ejb's from core.jar, so it can handle the command. What actually happens in the framework is that the the specific command ejb(cmdCreateBookEJB) in my example is cast to CommandEJB and then it's execute method is called.
The question is how to make the framework know about command ejbs.
I know that one option is to specify am env-entry in ejb-jar.xml with the core jar module name, and then use #Resource in commandExecutorEJB to find the entry, and then use the JNDI lookup to find the resource that would be cast to CommandBean.
But, I would like not to use ejb-jar.xml as we're using ejb 3.2 and ejb-jar.xml isn't necessary anymore.
EDIT:
To better explain here is how the jndi lookup string would look like for my example: java:app/core.jar/cmdCreateBookEJB
Because framework isn't and shouldn't be aware of the core.jar(The name core.jar name is just an example, someone could name it BookStoreCore.jar), I somehow need to pass module name(in my example core.jar), so that the framework know where to look for classes to find a specific command EJB, in my example cmdCreateBookEJB.
I know that I can use an env-var in ejb-jar.xml to pass module name to the framework. Here's an example:
<session>
<ejb-name>CommandExecutorEJB</ejb-name>
<ejb-class>com.mypackage.CommandExecutorEJB</ejb-class>
<session-type>Stateless</session-type>
<env-entry>
<env-entry-name>com.mypackage.CommandExecutorEJB/moduleName</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>core</env-entry-value>
</env-entry>
</session>
But, I would love to eliminate ejb-jar.xml from our project setup
You're using Java EE 7.
You can completely avoid class visibility problems by putting everything in your WAR file. core.jar and framework.jar can both be added to your WEB-INF/lib directory.
You can then directly inject EJBs where ever they're needed.
Related
We are trying to use spring-test's SpringExtension to write integration tests for our Spring and Hibernate-based Tomcat web application. Our sessionFactory bean configuration has the property configured mappingJarLocations with a sample value as /WEB-INF/lib/company-common*.jar which contains hibernate mapping files. In both actual deployment and Eclipse dev deployment, this works fine as the docBasePath (in Servlet environment) is appended to this pattern and the files are getting resolved. But this is not the case while running JUnit test cases either in a local or a CI environment.
We tried our best to use the provided support by having few overridden implementations of WebTestContextBootstraper, GenricXmlWebContextLoader, XmlWebApplicationContext, and WebDelegatingSmartContextLoader but had to finally give up as we cannot override the final method org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(MergedContextConfiguration) to provide the custom implementation of XmlWebApplicationContext. Our current approach is to manually create the application context and use it in the tests.
Here is the project structure:
Project_WebApp
|--src/**
|--WebContent/**
|--pom.xml
When the app is packaged as Project_WebApp.war, the dependencies are inside WEB-INF/lib from the root of extracted war. When deployed as a webapp in Tomcat using Eclipse, the dependencies are copied to <Eclipse_Workspace_Dir>/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/Project_WebApp/WEB-INF/lib. In both cases, the dependencies are available at <Resource_Base_Path>/WEB-INF/lib and Resource_Base_Path has no relation to Project_WebApp base directory.
Questions:
Did any one use SpringExtension in a scenario similar to above? If so can you suggest any alternative approaches?
Instead of /WEB-INF/lib/company-common*.jar, we tried a classpath-based pattern but didn't work as the obtained class path resources don't match the pattern. Is there anything else to try here?
I have an application packed in .ear file. This is the structure:
EmployeeManager
|---EmployeeManagerEJB.jar
---src/ (1)
|---EmployeeManagerJSF.war/
---index.xhtml
---WEB-INF/
---classes/ (2)
---lib/
|---lib/
---EmployeeManagerIntegration.jar
---src/ (3)
I use CDI to inject to classes located in (2) EJBs which interfaces are in (3) and implementations are in (1). However CDI throws exception " Unsatisfied dependencies for type ...". I assume something is wrong with my EAR structure. What should I do to fix this thing up?
CDI does not work by default between sub-deployments as they do not use the same classloader.
You could try placing your CDI beans in the EAR/lib folder this may work
make sure all sub-deployments have beans.xml in them if they are using CDI
there is no reason for this to be an EAR deployment, you can put both jars in WAR/lib and things will work fine
You can define inter-sub-deployment dependencies by adding class-path values into meta-inf/manifest.mf (This is somewhat standard between containers, here's the wildfly example: https://docs.jboss.org/author/display/WFLY8/Class+Loading+in+WildFly)
Or you can rely on your container implementation and turn off sub-deployment isolation (For wildfly see the following: https://docs.jboss.org/author/display/WFLY8/Class+Loading+in+WildFly)
You could copy your CDI beans to each sub-deployment that use them
Here is my needs :
I have a WebService application running on a JBoss 5.1 (with a jboss-classloading configuration export-all=NON_EMPTY and import-all=true).
I want to add some interceptors on it but I can't change the legacy WS WAR.
What is my problems :
I managed to get working a simple interceptor packaged in a JAR that basically log every calls on legacy WebService.
But to achieve my goal, I need to use JAR dependencies like XML parsers, business objects, etc...
How can I package my AOP interceptors and its dependencies in one file ?
What I've tried :
In a WAR package, I have to use a similar jboss-classloading strategy to avoid conflicts, but in this context, I can't intercept anything else than classes in the WAR itself, so I can't intercept legacy WS calls.
PS : I have made all the basics to get JBoss AOP working properly :
pluggable-instrument.jar in bin folder
run.conf with -javaagent:pluggable-instrumentor.jar
aop.xml with loadTimeWeaving enabled and include package defined
jboss-aop.xml with valid pointcuts configurations (which I want in my package)
For now I found a solution by building a SAR package (JBoss Service Archive).
The SAR file look like this :
aop-interceptors.sar
META-INF/jboss-service.xml
aop-interceptors.jar
META-INF/jboss-aop.xml
com.mypackage.aop.interceptors...
com.mypackage.aop.handlers...
com.mypackage.aop.business.logic...
xml-parsers.jar
business-objects.jar
...
The SAR file is deployed in folder : jboss-5.1/server/default/deployers/jboss-aop-jboss5.deployer/
I don't know what SAR package is supposed to do ... is there a better way to do it ?
The issue I am currently experiencing is that my entityManager fails to be injected during the execution of a web application deployed within an ear.
The ear is setup as follows:
/META-INF -application.xml (EJBJar +
WAR)
-MANIFEST.MF
-weblogic-application.xml (currently just the default one that eclipse
generates)
/APP-INF
-lib
-EJBClientJar (interfaces + pojos)
-other jars
-classes
EJBJar
/META-INF
-persistence.xml
/src
-Annotated classes
WAR
-Service classes
Classes are as follows:
DAO inside EJBJar
#Stateless(mappedName="AwesomeBean")
public class Awesome implements AwesomeRemote //AwesomeRemote in EJBClientJar
{
#PersistenceContext
EntityManager em;
}
public class AwesomeService //Inside WAR
{
AwesomeRemote = context.lookup (Awesome.path.to.AwesomeRemote) //Is found
}
The call stack is like this:
War -> EJBClientJar -> EJBJar
On the EJB jar the entity manager is null. Question being how do I ensure that the PersistenceContext gets injected? The JNDI lookup succeeds on the AwesomeRemote Interface. The Interface has no annotations on it.
It's probably due to the fact that you try to inject on POJO class, not on managed component. Could you try to mark it as #Stateless and public and check whether it works?
For simple testing you can also add #WebService annotation and invoke your bean with SoapUI for example.
You should read about "packaging" part of ejb specifications.
This structure should be sufficient and work:
/
/lib
EJBClientJar (interfaces + pojos)
/META-INF
persistence.xml
application.xml
EJBJar.jar
WAR.war
As some formatting was lost, I'm not sure about what wasn't right in yours.
If this still doesn't work, try removing the only tricky part from above: put all classes from EJBClientJar in root. You the just have the most simple EAR packaging possible, it just will work.
Also, if you don't use your session bean outside a web application, you could use #Local instead of #Remote .
I'm working on a project which includes persistence library (JPA 1.2), EJB 3 and Web presentation layer (JSF). I develop application using Eclipse and application is published on Websphere Application Server Community Edition (Geronimo 2.1.4) through eclipse plugin (but the same thing happens if I publish manually). When publishing to server I get the following error:
java.lang.NoClassDefFoundError: Could not fully load class: manager.administration.vehicles.VehicleTypeAdminBean
due to:manager/vehicles/VehicleType
in classLoader:
org.apache.geronimo.kernel.classloader.TemporaryClassLoader#18878c7
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:177)
at org.apache.xbean.finder.ClassFinder.(ClassFinder.java:146)...
In web.xml I have reference to EJB:
<ejb-local-ref>
<ejb-ref-name>ejb/VehicleTypeAdmin</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>manager.administration.vehicles.VehicleTypeAdmin</local>
<ejb-link>VehicleTypeAdminBean</ejb-link>
</ejb-local-ref>
EJB project has a reference to persistence project, and Web project has references to both projects. I don't get any compilation errors, so I suppose classes and references are correct.
I don't know if it is app server problem, but I ran previously application on the same server using same configuration parameters.
Does anybody have a clue what might be the problem?
Looks almost like it couldn't find the class manager.vehicles.VehicleType when it was attempting to create/load the class manager.administration.vehicles.VehicleTypeAdminBean.
I've encountered similar problems before. When the class loader attempts to load the class it looks at the import statements (and other class usage declarations) and then attempts to load those classes and so on until it reaches the bottom of the chain (ie java.lang.Object). If it cannot find one class along the chain (in your case it looks like it cannot load VehicleType) then it will state that it cannot load the class at the top of the chain (in your case VehicleTypeAdminBean).
Is the VehicleType class in a different jar? If you have a web module and and EJB module do you have the jar containing the VehicleType class in the appropriate place(s). Sometimes with web projects you have to put the jars in the WebContent/WEB-INF/lib folder or it won't find them.
Are both of these projects deployed separately (ie. two ears? or one ear and one war?) or are they together (ie, one ear with jars and a war inside?). I'm assuming the second given you declared your EJB local?
The jars that you are dependent on also have to be declared in your MANIFEST.MF files in the projects that use it.
I'm kind of running on guesses since I do not know your project structure. Showing that would help quite a bit. But I'd still check on where VehicleType is located with regards to your EJB class. You might find it isn't where you think it is come packaging or runtime.
Thanks #Chris for WebContent/WEB-INF/lib idea ! it works for me by following these steps :
1- Export my EJBs to a JAR (MyEJBs.jar)
2- I created another jar with your_installation_path/IBM/SDP/runtimes/your_version/binCreateEJBStrub.bat via CMD.exe, by executing this command :
createEJBStubs.bat <my_path>/MyEJBs.jar -newfile –quiet
3- A new jar will be automatically created in the same directory as MyEJBs.jar named MyEJBs_withStubs.jar
4- Put your new jar in WebContent/WEB-INF/lib
5- Call your EJBs by :
MyEJBRemote eJBRemote;
InitialContext ic = new InitialContext();
obj = ic.lookup("your_ejb_name_jndi");
eJBRemote = (MyEJBRemote ) PortableRemoteObject.narrow(obj,
MyEJBRemote.class);
eJBRemote = (MyEJBRemote ) obj;
Now you can call your EJBs from another EAR