I'm trying to create a webservice that gives some results taken through hibernate from the database.
#Path("/book")
public class BookService {
#Inject
private dbController db;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getBookTitle() {
return "H2G2";
}
#GET
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
public Response getUsers(){
List<UserEntity> users = db.getUsers();
return Response.ok(users,MediaType.APPLICATION_JSON).build();
}
}
the db variable whenever I call http://localhost/book/users is always null.
The dbController is:
public class dbController {
#Inject
private HibernateUtil util;
public List<UserEntity> getUsers(){
List<UserEntity> result = null;
try{
result = (List<UserEntity>) this.util.createQuery("select e from UserEntity e");
}catch (Exception e){
System.out.println(e.getMessage());
}
return result;
}
}
and the HibernateUtil is:
public class HibernateUtil {
private static final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");
private EntityManager entityManager = null;
private void createEntityManager(){
if (this.entityManager==null){
this.entityManager = entityManagerFactory.createEntityManager(); // here is your persistence unit name
}
}
private void closeConnection(){
this.entityManager.close();
this.entityManager = null;
}
public List createQuery(String query) throws Exception{
this.createEntityManager();
List result;
try{
result = this.entityManager.createQuery(query).getResultList();
}catch (Exception e){
throw new Exception(e.getMessage());
}
return result;
}
}
I'm using intellij and I added a break point at the db.getUsers() and set the variable db by adding new dbController(). However, the Intellij gives me the error "Class not loaded : controller.dbController".
The hibernate works for sure...so the problem is not there. It's the first time I'm trying to use Dependency Injection, but I'm not sure what I'm doing wrong.
Thanks
You cannot inject POJO it has to be a Bean. So making it a bean requires the annotations, for example:
#Stateful
#LocalBean
public class dbController {..} // Should be DbController, start with CAPS
and
#Stateful // or maybe #Stateless ?
#LocalBean
public class HibernateUtil {..}
Then when you have a Bean it is not allowed to use static final so change like this is needed:
private EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("NewPersistenceUnit");
But actually the easiest way to get EntityManager is just to inject it also. Like:
#PersistenceContext// maybe also with unit name (unitName = "whatever_the_unit_name_is")
private EntityManager em;
Related
Good afternoon, I am trying to get the data from my database. My application is with abse in microservices which has the following
This is my class for the database configuration.
#ApplicationScoped
public class DbConfig {
#Inject
#ConfigProperty(name = "db.connection.username")
private String dbUser;
#Inject
#ConfigProperty(name = "db.connection.password")
private String dbPassword;
#Inject
#ConfigProperty(name = "db.connection.url")
private String dbUrl;
#Produces
#ApplicationScoped
public EntityManager entityManager() {
Map<String, String> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.url", dbUrl);
properties.put("javax.persistence.jdbc.user", dbUser);
properties.put("javax.persistence.jdbc.password", dbPassword);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence-books", properties);
return emf.createEntityManager();
}
}
This is my RepositoryImpl class book
#ApplicationScoped
public class BookRepositoryImpl implements BookRepository {
#PersistenceContext
EntityManager entityManager;
#Override
public List<Book> findAll() {
try {
TypedQuery<Book> query = entityManager.createQuery("SELECT b FROM Book b ORDER BY b.id ASC", Book.class);
return query.getResultList();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
..// another CRUD methods
This is my rest class
#ApplicationScoped
#Path("/books")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class BookRest {
#GET
public List<Book> findAll() {
System.out.println("Buscando todos");
return bookService.findAll();
}
..// another CRUD Methods
}
The problem arises when I start the application through the server class, it starts correctly at localhost:7001, but in order to verify that it is working correctly I need to list the data in the database through localhost:7001/books, which gives me this error Cannot invoke "jakarta.persistence.EntityManager.createQuery(String, java.lang.Class)" because "this.entityManager" is null
in my session i need to call 2 diffrent procedures which are on db1 and db2. it works fine when i call them separetely but it fails when i call them in same session. it fetches first data correctly but it fails on second call since it looks for the second procedure on db1 although entitiymanager's datasource changed correctly.
what am i missing?
here is code snippet
#Repository
#Transactional
public class DB1Dao {
#PersistenceContext()
private EntityManager entityManager;
#SuppressWarnings("unchecked")
public Model1 getData(String param1) {
.....
}
}
#Repository
#Transactional
public class DB2Dao {
#PersistenceContext()
private EntityManager entityManager;
#SuppressWarnings("unchecked")
public Model2 getData(String param2) {
.....
}
}
#Autowired
private DB1Dao dao1;
#Autowired
private DB2Dao dao2;
#RequestMapping(value = "/inquiry", method = RequestMethod.POST)
public ResponseEntity<Object> inquiryService(#RequestBody InquiryRequest inquiryRequest){
....
Model1 model1 = dao1.getData(param2); // success
....
Model2 model 2 = dao2.getData(param2); // fails since it looks for second procedure on db1
}
You didn't show any persistence-related configuration info, but I'd guess you should differentiate your repositories by properly naming them:
#PersistenceContext(unitName = "db1PersitenceUnitName")
private EntityManager entityManager;
I work on a project developed by a team mate but we are facing a strange issue that drive me crazy: database is never updated and there's no exception in the logs. Here's the code:
#Service
#Transactional
public class InterventionProjectResultIntegrator implements IInterventionProjectResultIntegrator {
private static final ILogger logger = ComponentLogger.getInstance(InterventionProjectResultIntegrator.class);
private Dao dao;
private String APPLICATION = "APP";
#Autowired
public void setDao(Dao dao){
this.dao = dao;
}
#Override
public void integrateResponse() {
try {
List<ResponseEntity> responseListByStatus = dao.findAllResponseByStatus(Dao.STATUS_EN_COURS, APPLICATION);
for (ResponseEntity response: responseListByStatus ) {
response.setStatus(Dao.STATUS_OK);
dao.mergeResponseEntity(response);
}
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
throw ex;
}
}
}
As you can see the function is pretty simple:
Getting objects from database
Loop over the objects
Update Each object status
At the end of the loop commit changes
Everything run fine except that the objects are not updated on database and that there is no exception.
The Dao come from a maven dependency that worked fine in another project so I assume that the problem is related to the new one.
I can see following logs in console:
org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder#6dcee890] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean#713e49c3] bound to thread org.hibernate.event.internal.AbstractSaveEventListener - Persistent instance of: com.domain.ResponseEntity
org.hibernate.event.internal.DefaultMergeEventListener - Ignoring persistent instance
org.hibernate.action.internal.UnresolvedEntityInsertActions - No entity insert actions have non-nullable, transient entity dependencies.
Did you already face similar issue ?
Regards.
[EDIT 1]
As pointed out in comment, I replaced manual transaction handling with #Transactional annotation. See the code updated.
So now I have a new line in the logs, but the same result, object is not save in database.
org.springframework.transaction.interceptor.TransactionAspectSupport - Completing transaction for [com.response.InterventionProjectResultIntegrator.integrateResponse]
As asked the DAO source. This code is not under my responsability, and worked like a charm in another context.
#Repository
public class Dao {
public static final ILogger logger = ComponentLogger.getInstance(Dao.class);
public static final String STATUS_EN_COURS = "PENDING";
public static final String STATUS_OK = "OK";
public static final String STATUS_ERROR = "ERROR";
#PersistenceContext
protected EntityManager entityManager;
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void mergeMvzResponseEntity(ResponseEntity responseEntity) {
if(entityManager != null) {
this.entityManager.merge(responseEntity);
} else {
logger.error("Entity manager not initialized");
}
}
As suggested, I have reworked the source code to use #Transactional annotation, and to let Spring handle transaction stuff:
#Service
#Transactional
public class InterventionProjectResultIntegrator implements IInterventionProjectResultIntegrator {
private static final ILogger logger = ComponentLogger.getInstance(InterventionProjectResultIntegrator.class);
private Dao dao;
private String APPLICATION = "APP";
#Autowired
public void setDao(Dao dao){
this.dao = dao;
}
#Override
public void integrateResponse() {
try {
List<ResponseEntity> responseListByStatus = dao.findAllResponseByStatus(Dao.STATUS_EN_COURS, APPLICATION);
for (ResponseEntity response: responseListByStatus ) {
response.setStatus(Dao.STATUS_OK);
dao.mergeResponseEntity(response);
}
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
throw ex;
}
}
}
Then added this line to my xml configuration file:
<tx:annotation-driven/>
Now it works like a charm. Thanks to #M. Deinum to have pointed it out.
I am somewhat new to Java EE (dependency injection) and I can't figure out why #Inject is giving me null, yet InitialContext.doLookup does work.
Here is my bean. It is just a DAO. A wrapper for EntityManager basically
#Stateless
public class PersonManager {
#PersistenceContext("unitName="PersonData")
EntityManager em;
...
}
Here is a REST service, where I am trying to utilize PersonManager:
#Path("/PersonService")
#RequestScoped
public class PersonService {
#Inject private PersonManager manager; //this comes up null
#GET
#Produces("text/html")
public String getAllPersons() {
List<Person> personList manager.findAll(); //null pointer exception, manager null
}
}
Now what is weird is, if I do a lookup on PersonManager, it does work, like this:
#GET
#Produces("text/html")
public String getAllPersons() {
try {
manager = InitialContext.doLookup("java:global/PersonApp/PersonData/PersonManager");
}
catch(Exception e) {
e.printStackTrace();
}
List<Person> personList manager.findAll(); //this works!
}
Any idea why #Inject doesn't work here? I am using an EAR with a WAR and JAR within it like this:
EAR (PersonApp)
--JAR (PersonData - ejb module - contains PersonManager)
--WAR (PersonRest - web module - contains PersonService)
The problem turned out to be adding PersonService as a singleton in the rest application registration.
#ApplicationPath("api")
public class RestApplication extends Application{
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
public RestApplication(){
//below line caused #Inject not to work. commented out
//singletons.add(new PersonService());
}
#Override
public Set<Class<?>> getClasses() {
return empty;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
I'm using JPA and EJBs on WebSphere 7.
I have the following class:
#Entity
#Table(name="WIDGET")
public class Widget implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String details;
/* getters and setters */
}
I have a DAO like so:
#Stateless
public class WidgetDAO implements WidgetDAOLocal {
#PersistenceUnit
private EntityManagerFactory emf;
private EntityManager em;
public EntityManager getEntityManager() {
if (emf == null) {
throw new Exception();
}
return emf.createEntityManager;
}
public Widget getWidget(Long id) {
Widget widget = null;
EntityManager em = getEntityManager();
try {
widget = (Widget)em.find(Widget.class, widgetId);
} finally {
em.close();
}
return widget;
}
public Widget createWidget(Widget widget) {
EntityManager em = getEntityManager();
try {
em.persist(widget);
em.flush();
} finally {
em.close();
}
return widget;
}
public Widget updateWidget(Widget widget) {
EntityManager em = getEntityManager();
try {
widget = getEntityManager().merge(widget);
em.flush();
} finally {
em.close();
}
return widget;
}
}
The create works fine and my widget appears in the database.
But when I try to do a merge, I get an error. The code to do the merge and the error I get follows:
public WidgetService {
#EJB
private WidgetDAO widgetDAO;
public WidgetDAO getWidgetDAO() {
return this.widgetDAO;
}
public Widget getWidget(Long id) {
return this.getWidgetDAO().getWidget(id);
}
public void updateDetails(Long widgetId, String details) {
Widget w = this.getWidget(widgetId);
w.setDetails(details);
this.widgetDAO.updateWidget(w);
}
}
The error is:
Exception caught from before_completion synchronization operation:
<openjpa-1.2.1-SNAPSHOT-r422266:686069 nonfatal user error> org.apache.openjpa.persistence.InvalidStateException:
The generated value processing detected an existing value assigned to this field: com.mydomain.domain.Widget.id.
This existing value was either provided via an initializer or by calling the setter method.
You either need to remove the #GeneratedValue annotation or modify the code to the initializer processing.
Any help on this is greatly appreciated!
Merge takes a copy of your entity, detaches it and persists the new one, which i presume attempts to set the ID from the old and causes you the conflict on your generated values. If you just want to update your object you should do so within a transaction and commit that.
Thanks for the help everybody, I figured it out, here's the cause of the problem and the solution that worked for me.
In my DAO I was doing this:
#Stateless
public class WidgetDAO implements WidgetDAOLocal {
#PersistenceUnit
private EntityManagerFactory emf;
private EntityManager em;
public EntityManager getEntityManager() {
if (emf == null) {
throw new Exception();
}
return emf.createEntityManager;
}
Because the EntityManagerFactory was being injected via the #PersistenceUnit annotation, the entities were "Application-Managed", causing some kind of conflict with WebSphere.
I changed the code to this:
#Stateless
public class WidgetDAO implements WidgetDAOLocal {
#PersistenceContext
private EntityManager em;
public EntityManager getEntityManager() {
return em;
}
public Widget updateWidget(Widget widget) throws Exception {
return getEntityManager().merge(widget);
}
The #PersistenceContext annotation causes the entities to be "Container-Managed", and everything works now.
Thanks for the all the help and suggestions here. At the end of the day, I worked out the solution after re-focusing on the "Managing Entities" section of the documentation here:
http://docs.oracle.com/javaee/5/tutorial/doc/