My client runs on Tomcat and Server is on Wildfly 11.
The EJB is:
package dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import model.User;
#Stateless
public class UserDaoImpl implements UserDao {
#PersistenceContext(unitName = "nju")
protected EntityManager em;
#Override
public String login(String userName, String password) {
try {
Query query = em.createQuery("from User u where u.userName='" + userName + "'");
#SuppressWarnings("unchecked")
List<User> list = query.getResultList();
em.clear();
if (list.isEmpty()) {
return "failure";
} else if (list.get(0).getPassword().equals(password)) {
return "success";
}
} catch (Exception e) {
e.printStackTrace();
return "failure";
}
return "failure";
}
}
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="nju">
<description>This unit manages users.</description>
<jta-data-source>java:/MySqlDS</jta-data-source>
<properties>
<property name="showSql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</properties>
</persistence-unit>
When I run server, the output contains
18:53:38,997 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool -- 62) WFLYCLINF0002: Started client-mappings cache from ejb container
18:53:39,005 INFO [org.jboss.as.jpa] (ServerService Thread Pool -- 62) WFLYJPA0010: Starting Persistence Unit (phase 2 of 2) Service 'J2EEServer.war#nju'
So the location of persistence.xml is not wrong.
However, when I run client and call the function in EJB. There is NullPointerException which indicates that the entitymanager is not injected.
In client I use a factory to get EJB. The method is
private static Object getEJB(String JNDIPath) {
Hashtable<String, String> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
try {
Context context = new InitialContext(jndiProperties);
return context.lookup(JNDIPath);
} catch (NamingException e) {
e.printStackTrace();
}
return null;
}
The exception only shows on wildfly and when it occurs, the tomcat message is
org.jboss.ejb.client.EJBClient <clinit>
INFO: JBoss EJB Client version 2.1.4.Final
org.xnio.Xnio <clinit>
INFO: XNIO version 3.4.0.Final
org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.4.0.Final
org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 4.0.21.Final
org.jboss.ejb.client.remoting.VersionReceiver handleMessage
INFO: EJBCLIENT000017: Received server version 3 and marshalling strategies [river]
org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext#51e6ae57, receiver=Remoting connection EJB receiver [connection=org.jboss.ejb.client.remoting.ConnectionPool$PooledConnection#5281b661,channel=jboss.ejb,nodename=microwin10-115]} on channel Channel ID 8d8bb52c (outbound) of Remoting connection 3607d423 to localhost/127.0.0.1:8080 of endpoint "client-endpoint" <41cb456e>
org.jboss.ejb.client.remoting.ChannelAssociation$ResponseReceiver handleEnd
INFO: EJBCLIENT000016: Channel Channel ID 8d8bb52c (outbound) of Remoting connection 3607d423 to localhost/127.0.0.1:8080 of endpoint "client-endpoint" <41cb456e> can no longer process messages
How can I solve this problem?
I finally find the solution!!
In my project, my previous Service code is
#Stateless
public class UserServiceImpl implements UserService {
private UserDao userdao=Factory.getUserDao();
#Override
public String login(String userName, String password) {
return userdao.login(userName, password);
}
#Override
public String register(User user) {
return userdao.register(user);
}
}
And in the Factory, I get the object by using new UserDaoImpl(). That's the question!
The EntityManager will not be injected if the object is used like this way.
So I delete the Factory and change the code in Service
#Stateless
public class UserServiceImpl implements UserService {
/**
* Will be injected
*/
#EJB
private UserDao userdao;
#Override
public String login(String userName, String password) {
return userdao.login(userName, password);
}
#Override
public String register(User user) {
return userdao.register(user);
}
}
That works perfectly.
Related
I'm trying to run a simple web application on which I want run some tests on Jakarta EE 9.1(Full platform). I deployed my application on Glassfish 6.2.5. While I was running some code with jpa implementation this exception is thrown(the persistence provider is EclipseLink 3.0.2):
jakarta.persistence.PersistenceException: Exception [EclipseLink-4002]
(Eclipse Persistence Services - 3.0.2.v202107160933):
org.eclipse.persistence.exceptions.DatabaseException Internal
Exception: java.sql.SQLException: No suitable driver found for
jdbc:mysql://localhost:3306;create=true Error Code: 0
The persistence.xml is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="GestoreDB" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>testJPA.ValueBeen</class>
<properties>
<property name="jakarta.persistence.schema-generation.action" value="drop-and-create"/>
<property name="jakarta.persistence.schema-generation.scripts.create-target" value="database-and-scripts"/>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306;create=true"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="myPwd"/>
</properties>
</persistence-unit>
</persistence>
The Entity is(getters and setters omitted):
#Entity
#NamedQuery(name = "ValueBeen.selectTable", query = "select u from ValueBeen u")
public class ValueBeen
{
public ValueBeen(){
}
public ValueBeen(String value)
{
this.value = value;
}
public ValueBeen(int id, String value)
{
this.id = id;
this.value = value;
}
#Id
#GeneratedValue
private int id;
#NotNull
private String value;
...
}
And the WebServlet who perform persistency is:
#WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ValueBeen valueBeen=new ValueBeen("Hello");
//Manager persistence and manager been
EntityManagerFactory managerPersistence = Persistence.createEntityManagerFactory("GestoreDB");
EntityManager entityManager = managerPersistence.createEntityManager();
//Do persistence
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(valueBeen);
transaction.commit();
//close managers
entityManager.close();
managerPersistence.close();
}
}
I put the jdbc connector jar (Mysql connector 8.0.28) in .\glassfish-6.2.5\glassfish\domains\domain1\lib
As you deploy your app to glassfish container then "transaction-type" in persistence.xml i guess should be "JTA", and property "jakarta.persistence.jdbc.url" is invalid because you do not indicate any database / schema name after ":3306". Glassfish documentation provides instructions and examples how to setup global jdbc connections and those limited to only application scope.
WildFly 10.1 used. In modules added single module that contains jar file with interface EzRegistryService.
Producer code:
package com.ejbtest;
import org.apache.log4j.Logger;
import javax.ejb.EJB;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Produces;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Resources {
private static final Logger log = Logger.getLogger(Resources.class);
public static final String jndiName = "java:global/ejbtest.main/EzRegistryServiceBean!com.ejbtest.EzRegistryService";
//also didn't work
//#Produces
//#EJB(lookup = jndiName)
//private EzRegistryService ezRegistryService;
// didn't work
#Produces
public EzRegistryService getEzRegistryService() {
log.info("getEzRegistryService called");
try {
InitialContext ctx = new InitialContext();
Object service = ctx.lookup(jndiName);
log.info("Found: " + service);
return (EzRegistryService) service;
} catch (NamingException e) {
log.error("Exception while getting EzRegistryService", e);
return null;
}
}
}
Singleton bean:
package com.ejbtest;
import org.apache.log4j.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
#Singleton
#Startup
public class MyGateStartup {
private static final Logger log = Logger.getLogger(MyGateStartup.class);
//#EJB(mappedName = Resources.jndiName) //works fine
#Inject
private EzRegistryService service;
#PostConstruct
public void start() {
log.info("MyGateStartup started");
//...
}
#PreDestroy
public void end() {
//...
log.info("MyGateStartup stopped");
}
}
beans.xml in WEB-INF folder:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1"
bean-discovery-mode="all">
</beans>
WildFly can't deploy resulting war-file:
2017-03-14 13:15:05,237 MSC service thread 1-8 INFO [org.jboss.weld.deployer] WFLYWELD0006: Starting Services for CDI deployment: ejbtest.gate-1.0-SNAPSHOT.war
2017-03-14 13:15:05,241 MSC service thread 1-8 INFO [org.jboss.weld.deployer] WFLYWELD0009: Starting weld service for deployment ejbtest.gate-1.0-SNAPSHOT.war
2017-03-14 13:15:05,299 MSC service thread 1-6 ERROR [org.jboss.msc.service.fail] MSC000001: Failed to start service jboss.deployment.unit."ejbtest.gate-1.0-SNAPSHOT.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."ejbtest.gate-1.0-SNAPSHOT.war".WeldStartService: Failed to start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.6.Final.jar:1.2.6.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_121]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_121]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_121]
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type EzRegistryService with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject private com.ejbtest.MyGateStartup.service
at com.ejbtest.MyGateStartup.service(MyGateStartup.java:0)
Why CDI can't find producer in Resources class?
In CDI specification, it is written in section 2.5:
Producer methods (as defined in Producer methods) whose bean class does not have a bean defining annotation are not discovered....
The class where you have your #Produces annotated method must be a CDI bean. Try giving it a scope :)
Looks like CDI is not managing your Resources class.
Once it's just a factory bean, you can annotated it with #ApplicationScoped:
#ApplicationScoped
public class Resources {
...
}
hi i'm using netbeans+glassfish
i'm trying to run this code:
i only create DB without any table ( by running this code i want to create tables and persist my object)
public static void main(String[] args) {
SmartphoneService ss = new SmartphoneService();
Smartphone smart = new Smartphone(0, 0, null, null, null);
ss.create(smart);
}
but i got this error :
Unable to lookup JNDI name
my persistence.xml:
<persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:comp/env/jdbc/mysql</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
my class smartphoneservice:
#Stateless
public class SmartphoneService implements IDao<Smartphone> {
private static final String JPQL_SELECT_PAR_ID = "SELECT u FROM Smartphone u WHERE u.idSmartphone=:id";
private EntityManagerFactory emf;
private EntityManager em;
public SmartphoneService() {
emf = Persistence.createEntityManagerFactory("manager1");
em = emf.createEntityManager();
}
public boolean create( Smartphone smart) {
try {
em.getTransaction().begin();
em.persist(smart);
em.getTransaction().commit();
return true;
} catch (Exception e) {
if (em.getTransaction() != null) {
em.getTransaction().rollback();
}
} finally {
em.close();
emf.close();
}
return false;
}}
i checked my connection pool ping ( Ping Succeeded )
thanks for ur help
You're mixing up a JavaSE and with a JavaEE environment.
Your datasource looks like it's configured on Glassfish (Java EE environment). So the JNDI name java:comp/env/jdbc/mysql will only be available in a Java EE context.
Your SmartphoneService is being run in a Java SE context (via a public static void main() method. When you try to do a lookup of java:comp/env/jdbc/mysql, it's not going to be there because the DataSource only exists in your Glassfish (Java EE) environment.
You will need to perform JNDI lookups from the same context that the resources were registered in. My suggestion would be to make your SmartphoneService code run on Glassfish. There are lots of ways to drive that -- EJBs, Servlets, etc...
I'm trying to create EntityManager in my webapp, but it's failing with:
No suitable driver found for jdbc:postgresql:://localhost/database
However the same persistance unit and the same code for creating EntityManager works when I run it as JavaSE console application (from main() ).
Googling gave me several common problems causing that error:
JDBC url is wrong
Shouldn't be since it works from main
JDBC Driver is not in the class path
I can create a Class object using Class.forName("org.postgresql.Driver"); for the driver so I think it is in the classpath.
Other things I tried:
I thought maybe the driver jar from glassfish/lib and the webapp/WEB-INF/lib are conflicting somehow so I tried with both of them together and separately, no luck.
Recreated a small new webapp hoping the problem will go away, it didn't :-)
Inject #PersistanceUnit - also didn't work, don't know is it the same issue or I didn't use it properly as I'm still learning about injection and EJBs
Thanks
Full error:
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost/database Error Code: 0
Here is the code:
ManagedBean in webapp:
#ManagedBean
public class TestBean {
private String entry;
private String driver;
public String getFromDatabase(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Unit1");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
EntityOne one = new EntityOne();
one.id = 1;
one.entry = "Bla bla";
em.persist(one);
tx.commit();
em.close();
return "done";
}
public String createDriver(){
try {
Class d = Class.forName("org.postgresql.Driver");
driver = d.getName();
} catch (ClassNotFoundException e) {
driver = "Class not found";
return "";
}
return "";
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getEntry() {
return entry;
}
public void setEntry(String entry) {
this.entry = entry;
}
}
Same code working in main:
public class Standalone {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Unit1");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
EntityOne one = new EntityOne();
one.id = 1;
one.entry = "Bla bla";
em.persist(one);
tx.commit();
em.close();
}
}
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="Unit1" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.test.EntityOne</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/database"/>
<property name="javax.persistence.jdbc.user" value="darko"/>
<property name="javax.persistence.jdbc.password" value="sifra"/>
<property name="eclipselink.target-database" value="PostgreSQL"/>
</properties>
</persistence-unit>
Place the posgres jdbc driver into the lib of glassfish. Its something like this.
[glassfish_home]/glassfish/domains/YOUR_DOMAIN/lib/
Also, restart the server after this.
I have an issue with injecting a service to predefined interceptor using google guice.
What i'm trying to do is to use emptyinterceptor to intercept changes with entities. Interceptor itself works fine, the problem is that I can't figure out how to inject a service to it. Injections themselves work fine throughout the whole application.
persistence.xml
<persistence 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_2_0.xsd"
version="2.0">
<persistence-unit name="db-manager">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>test.Address</class>
<properties>
<property name="hibernate.ejb.interceptor" value="customInterceptor"/>
</properties>
</persistence-unit>
how im trying to inject
public class CustomInterceptor extends EmptyInterceptor {
private static final Logger LOG = Logger.getLogger(CustomInterceptor.class);
#Inject
private Provider<UploadedFileService> uploadedFileService;
...
}
how JpaPersistModule is initiated
public class GuiceListener extends GuiceServletContextListener {
private static final Logger LOG = Logger.getLogger(GuiceListener.class);
#Override
protected Injector getInjector() {
final ServicesModule servicesModule = new ServicesModule();
return Guice.createInjector(new JerseyServletModule() {
protected void configureServlets() {
// db-manager is the persistence-unit name in persistence.xml
JpaPersistModule jpa = new JpaPersistModule("db-manager");
...
}
}, new ServicesModule());
}
}
how services are initiated
public class ServicesModule extends AbstractModule {
#Override
protected void configure() {
bind(GenericService.class).to(GenericServiceImpl.class);
bind(AddressService.class).to(AddressServiceImpl.class);
}
}
I searched for hours and have find no real solution, so the ugly workaround I am using is to create 2 interceptors.
The first one is bound correctly by hibernate but does not have anything injected. It calls the second interceptor via some other mechanism - in the example below via a static reference to the InjectorFactory. The second interceptor is not bound to Hibernate, but like any other class, it can happily have stuff injected into it.
//The first ineterceptor has methods like this...
#Override
public synchronized void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
InjectorFactory.getInjector().getInstance(MyOtherInterceptor.class).onDelete(entity, id, state, propertyNames, types);
}
d
//The second one has the real implementation
#Inject
public MyOtherInterceptor() {
}
#Override
public synchronized void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
//Full implementation
}
//etc