I'm writing my first Java EE (EJB + Servlets etc.) application (please note: I'm using Eclipse).
I'm stuck with a problem with EntityManager injection not working, and having some difficulties finding why due to my Java EE (and Java in general) noobness.
Here is my persistence.xml file - I think this is mostly correct, since I can launch the HSQL database manager from the JMX console and my PUBLIC.USER table shows up correctly.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="MyPu">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
Here's my servlet code:
[...]
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
String id = request.getParameter("username");
String password = request.getParameter("password");
UserManagerBean um = new UserManagerBean();
um.register(username, password);
RequestDispatcher dispatcher=getServletContext().getRequestDispatcher("/index.jsp");
dispatcher.forward(request, response);
}
And here's my UserManagerBean Class:
//bunch of imports
import myPackage.UserManager;
public #Stateful class UserManagerBean implements UserManager {
#PersistenceContext(unitName="MyPu")
private EntityManager persistManager;
public void register(String username, String password) {
User user = new User(userame, password);
persistManager.persist(user);
persistManager.flush();
}
}
The persistManager.persist(user) line throws a NullPointerException.
From my own searching I understood that this is happening because, since I'm calling new() on UserManagerBean the injection from the #PersistenceContext annotation never takes place and persistManager never gets bound.
If so, it is evident that I'm missing something about the proper usage of EJBs.
What is the right way to instantiate my bean? What's with the interfaces? I'm not entirely sure if my bean should be stateful or stateless :\
Additional info:
I changed code in my servlet, from
UserManagerBean um = new UserManagerBean();
to
#EJB
private UserManagerBean um;
in the appropriate place. Now um is the NullPointer.
Quoting Referencing EJB3 Session Beans from non-EJB3 Beans from the JBoss documentation:
JBoss Application Server 4.2.2 implemented EJB3 functionality by way of an EJB MBean container running as a plugin in the JBoss Application Server. This had certain implications for application development.
The EJB3 plugin injects references to an EntityManager and #EJB references from one EJB object to another. However this support is limited to the EJB3 MBean and the JAR files it manages. Any JAR files which are loaded from a WAR (such as Servlets, JSF backing beans, and so forth) do not undergo this processing. The Java 5 Enterprise Edition standard specifies that a Servlet can reference a Session Bean through an #EJB annotated reference, this was not implemented in JBoss Application Server 4.2.2.
So even though the Java EE 5 specification stipulates a wider scope of the #EJB annotation, JBoss 4.2.2 doesn't support it. In fact JBoss 4.2.2 is a transitional version that doesn't claim full Java EE 5 compliance.
Consequently, either:
Stick with you actual version of JBoss but use a JDNI lookup to get your bean - or -
Swith to JBoss 5 AS that fully supports the entire Java 5 Enterprise Edition specification (but has horrible startup performances) - or -
Swith to another Java EE 5 application server like GlassFish v2 (or even v3) or WebLogic 10. I'd go with GFv3.
As Petar Minchev said in the comments above #EJB doesn't work in servlets with JBoss 4.2.
In your WAR (in the WEB-INF directory) you'll need to modify two files:
web.xml:
<ejb-local-ref>
<ejb-ref-name>ejb/UserManager</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home/>
<local>myPackage.UserManager</local>
</ejb-local-ref>
jboss-web.xml:
<?xml version='1.0' encoding='ISO-8859-1'?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.3//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
<jboss-web>
<ejb-local-ref>
<ejb-ref-name>ejb/UserManager</ejb-ref-name>
<local-jndi-name>[earname]/UserManagerBean/local</local-jndi-name>
</ejb-local-ref>
</jboss-web>
You can then get an instance of your EJB by doing:
UserManagerBean um = (UserManager)new InitialContext().lookup( "java:comp/env/ejb/UserManager" );
As per the comments, it turns out that you indeed are using an appserver which doesn't support it at all -as I expected. To resolve this, you have 3 options:
Use "good old" XML config files.
Upgrade the server (there's already a stable 5.1.0).
Replace the server (I can recommend Glassfish v3 to be the most up-to-date).
To enable dependency injection on your project make sure that you have the file "beans.xml" and it is properly located.
For WAR packaging the location is src/main/webapp/WEB-INF/
For JAR and EAR packaging the location is src/main/resources/META-INF/
If you have several maven modules you must have it on each module.
More information about beans.xml
Related
I'm trying to init CDI-SE context inside my Quartz Application, so i have the following dependency (maven):
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>2.3.4.Final</version>
</dependency>
Inside my JobQuartz i have the method execute() with the following:
public void execute(JobExecutionContext context) throws JobExecutionException {
Weld weld = new Weld();
WeldContainer container = weld.initialize();
service = container.instance().select(MyService.class).get();
service.go();
weld.shutdown();
}
But i got the following error:
Caused by: java.lang.IllegalStateException: WELD-ENV-002009: Weld SE container cannot be initialized - no bean archives found
My project is a WAR, so i putted beans.xml file inside /src/main/webapp/META-INF/, see the content:
<?xml version="1.0"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.2" bean-discovery-mode="all">
</beans>
I copied the file to /src/main/resource/META-INF, but i got the same error.
After some conversation in comments section I think I understand enough to answer you.
First of all, you should not start Weld SE container on your own as you then have two containers running side by side (which isn't intended/supported) - one SE and one "classic", handled by the container. Stick with the container-handled one, which is booted for you effortlessly.
Now, I see you are missing some scope activation means. If you are using some newer version of Weld, you can make use of an interceptor, which will activate RequestContext (I suppose that's the one you are after) before a method and tear it down afterwards. All you need for that is a dependency on Weld API (which is included in WFLY anyway) and then you simply annotate your method or class with that.
For the above you need Weld 2.4.x. Note that you can quite simply patch your WildFly. The patches are at the bottom of the Weld website and the how-to can be found here.
If you were to use Weld 3/CDI 2.0 then there is even a built-in bean (RequestContextController) which allows you to control this lifecycle.
Other option is then Deltaspike, as Johm Ament pointed out, but that requires you to bring in another dependency.
If what you're trying to do is start a request context, you have a couple of solutions.
Use DeltaSpike's Quartz Integration for CDI - http://deltaspike.apache.org/documentation/scheduler.html
Programmatically start and stop a context using BoundRequestContext (it's a CDI bean you can inject).
I would strongly recommend the DeltaSpike approach, since it takes care of all of the setup you would need for the job to automatically start the context.
I have a webapp that is a RestEASY JAX-RS application and that uses the latest servlet specifications, such as Java EE annotations so that I don't need to create a web.xml file.
The webapp is bundled as foobar.war and dumped into the webapps directory in Tomcat. In fact the same foobar.war is deployed twice in the same Tomcat instance, once as foobar.war and the other as foobar#demo.war (which maps it to foobar/demo as you know).
I configure each mounted webapp by placing conf/Catalina/localhost/foobar.xml and conf/Catalina/localhost/foobar#demo.xml files, that look like this:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="foo" type="java.lang.String" value="bar"/>
</Context>
In my JAX-RS application I pull in the value of foo from JNDI using java:comp/env/foo.
So now I added a Java-based Spring configuration named FooBarConfiguration. I load it in my JAX-RS application using new AnnotationConfigApplicationContext(FooBarConfiguration.class). That all works fine.
So now I've added two profiles to FooBarConfiguration, one named foo and one named bar. But now... how do I tell the webapp which Spring profile to use? (Remember that I have no web.xml file.) Obviously I have to set spring.profiles.active somewhere. But where?
Because the documentation spoke of "environment" and "JNDI", I crossed my fingers and added an environment variable to conf/Catalina/localhost/foobar.xml:
<Environment name="spring.profiles.active" type="java.lang.String" value="foo"/>
No luck.
I can't set a system property, because that will apply to all the webapps, and the idea here is that each foobar.war instance (foobar.war and foobar#demo.war) could each have a different profile specified.
I suppose I could manually pull it out of the Tomcat environment myself, using java:comp/env/spring.profiles.active, but then where do I set the value? (I thought maybe AnnotationConfigApplicationContext would have a constructor where I could set the profile, or at least have a profile setting, but that also seems to be missing.)
(Plus if I'm manually pulling out the setting from JNDI and setting it myself, I might as well switch to the more lightweight Guice and manually load the modules I want. I'm only using the humongous, clunky Spring because it promised to allow easy selection of profiles.)
How can I indicate, external to my WAR file, on a per-webapp basis, which Spring profile I'm using?
You can set active profiles in many ways. Since you were searching for it via AnnotationConfigApplicationContext constructor, the one described here in spring docs might suit you.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.refresh();
The solution is to use AnnotationConfigWebApplicationContext instead of StandardServletEnvironment.
The trick is to get Spring to use a StandardServletEnvironment, which looks in several places including JNDI java:comp/env/... for spring.profiles.active. See http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-property-source-abstraction .
My problem is that AnnotationConfigApplicationContext uses a StandardEnvironment, which only looks in a few places for the profile designation. Switching to a AnnotationConfigWebApplicationContext made Spring use a StandardServletEnvironment:
final AnnotationConfigWebApplicationContext webContext =
new AnnotationConfigWebApplicationContext();
webContext.register(FooBarConfiguration.class);
webContext.refresh();
Now my webapp environment configuration in conf/Catalina/localhost/foobar.xml works:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="spring.profiles.active" type="java.lang.String" value="foo"/>
</Context>
I am using Wildfly 10.1.0 and I am trying to change all the EJB's to only use #Transactional annotations, which are provided since Jave EE 7 (because of JTA 1.2). The thing is when my project has 0 EJB's, the PersistenceUnit is not started by the container. If I add an empty class with only the annotation #Stateless then it works again.
This is my persistence.xml
<persistence version="2.1">
<persistence-unit name="Storage-PU" transaction-type="JTA">
<jta-data-source>java:/PostGreDS</jta-data-source>
<class>SomeEntity<class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
</persistence>
What is the reason why the PersistenceUnit is not started, when there are no EJB's available?
What is the reason why the PersistenceUnit is not started, when there are no EJB's available?
The reason is that in a JEE application the Persistence Context (including DB connection, Persistence Units and stuff) is started and managed by the EJB container:
So, just annotating beans methods at the Web tier with #Transactional is not enough to get Persistence Context started. Beware that transactions are also managed by the EJB container, not the Web Container.
See Java Platform, Enterprise Edition: The Java EE Tutorial for further details on JEE architecture.
I have problem in configuring JNDI lookup for ejb3.1 and weblogic 12c, jdk1.6
#Remote
public interface Bank{
public String accounts();
}
#Stateless(name="BankSession")
public class BankSessionBean implements Bank{
#Override
public String accounts() {
//////// }
ejb-jar.xml:
<enterprise-beans>
<session>
<display-name>BankSession</display-name>
<ejb-name>BankSession</ejb-name>
<business-remote>com.examples.Bank</business-remote>
<ejb-class>com.examples.BankSessionBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
<enterprise-beans>
weblogic-ejb-jar.xml:
<weblogic-enterprise-bean>
<ejb-name>BankSession</ejb-name>
<jndi-name>BankSession</jndi-name>
</weblogic-enterprise-bean>
client code:
When i start using Jndi Look up using this syntax
java:comp/env/ejb/BankSession
Its giving following error.
javax.naming.NameNotFoundException: While trying to lookup 'java:comp/env/ejb/BankSession' didn't find subcontext.
Here ejbbean and client code runs on different jvm's.
Which Jndi look up should i use ?
java:comp/env/ejb/BankSession'
java:global/applicationName/moduleName/BankSession
java:module/BankSession
java:app/moduleName/BankSession
java:comp/env/ejb/BankSession is working fine with ejb 3.0 and oc4j server.
When i migrate to ejb3.1 and weblogic 12c, its not working.
I even tried without using weblogic deployment xml files. Same issue encountered.
How should i configure my Jndi here ? Please help as i am facing this issue since long time.
For a lookup in the form of java:comp/env/... you need an EJB ref in the deployment descriptor of the component that does the lookup!
java:comp/env/... is always relative to the component that does the lookup.
A lookup name that is independent of the actual component that does the lookup and works from anywhere inside your application is 4.: java:app/moduleName/...
java:global/appName/... will fail if you decide to rename your ear file one day.
java:module/... only works inside a component that is part of the same module.
So 4. is IMO the best alternative.
I am trying to update a small alpha version of a enterprise application originally written in Java6. Now I want to use:
Java 7
JSF latest
Maven
EJB 3.2 with Glassfish
So far I can deploy my EAR file on Glassfish without problems. My webapp can be loaded, the first JSF pages navigate fine. And my JSF backing bean seems to also load my Stateless session beans fine. Debugging showed me, I can get from one SSB to another coming from my backing bean. The last and final step that I am missing is my entity manager and persistence.
My class is annoated with #Stateless and i am using:
#PersistenceContext(unitName = "myProjectPU")
protected EntityManager entityManager;
But the entity manager is null :(
My persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="myProjectPU" transaction-type="JTA">
<jta-data-source>jdbc/myProject</jta-data-source>
<properties>
<property name="javax.persistence.schema-generation.create-database-schemas" value="true" />
</properties>
</persistence-unit>
</persistence>
Any ideas? Does the persistence.xml have to be inside the ear maven module? Right now its in the ejb maven module, where my classes which use the entity manager reside.
Well finally I found the problem. Scrolling up in the glassfish logs showed that the nullpointer exception followed up an earlier exception that stated "No database selected". The problem was not in the code, but in the Glassfish JDBC Connection that I made. My ping worked fine and i thought the connection was ok. But you dont only have to add the mysql port and username and password. You also MUST change the default URL and add (additional properties in connection pool) the following value:
jdbc:mysql://localhost:3306/yourdatabase
before it was defaulted to:
jdbc:mysql://:3306/
Take also care that there are two parameters, Url and URL! After that not only the ping succeeded, but also the database connection with entity manager worked fine. :(