Why em.persist() has no effect on database table? - jpa

I have a RESTful service called AuthenticationEndpoint, which checks the users username/password pairs, creates token, save token to database and returns token to application client.
Code works without errors and exceptions.
UserEJB bean should save token to Token database table and AuthenticationEJB bean should update token field in User database table. But as I see in MySQL Workbench nothing is saved or updated.
UserEJB.getUsers() method work fine and return list of users and it seems that EJB container found persistence-unit ForthDynamicWebProject, but why I can't save and update entities? Thanks for your attention.
AuthenticationEndpoint RESTful service
#ApplicationScoped
#Path("/authentication")
public class AuthenticationEndpoint {
#Inject
AuthenticateEJB authenticateEJB;
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response authenticateUser(String jsonString) {
Gson gson = new Gson();
Credentials credentials = gson.fromJson(jsonString, Credentials.class);
String userName = credentials.getUserName();
String password = credentials.getPassword();
try {
User user = authenticateEJB.checkUser(userName, password);
if ((user instanceof User) && user != null) {
return Response.ok().header("token", user.getToken().getToken()).build();
} else {
return Response.status(Response.Status.FORBIDDEN).build();
}
} catch (Exception e) {
return Response.status(Response.Status.FORBIDDEN).build();
}
}
}
Here is the code of EJBs:
AuthenticateEJB
#LocalBean
#Stateless
public class AuthenticateEJB {
#PersistenceContext(unitName = "ForthDynamicWebProject")
EntityManager em;
#Inject
UserEJB userEJB;
public User checkUser(String userName, String password) {
List<User> users = userEJB.getUsers();
for (User user : users) {
if (user.getUsername().equals(userName) && user.getPassword().equals(password)) {
user.setToken(userEJB.updateToken());
em.merge(user);
return user;
}
}
return null;
}
}
UserEJB
#LocalBean
#Stateless
public class UserEJB {
#PersistenceContext(unitName = "ForthDynamicWebProject")
EntityManager em;
#Inject
Token token;
public List<User> getUsers() {
Query query = em.createQuery("from User");
return (List<User>) query.getResultList();
}
public Token updateToken() {
em.persist(token);
return token;
}
}
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="ForthDynamicWebProject" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/second_attempt_hibernate</jta-data-source>
<class>converters.ConverterLocalDateTime</class>
<class>entity.DocStatus</class>
<class>entity.DocType</class>
<class>entity.Document</class>
<class>entity.Employee</class>
<class>entity.MailOrder</class>
<class>entity.MailOrderStatus</class>
<class>entity.Token</class>
<class>entity.User</class>
</persistence-unit>
</persistence>
UPDATE:
Token entity
#Entity
#Table(name = "tokens")
#NamedQuery(name = "Token.findAll", query = "SELECT t FROM Token t")
public class Token implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Temporal(TemporalType.TIMESTAMP)
private Date loginTime;
private String token;
// bi-directional one-to-one association to User
#OneToOne(mappedBy = "token")
private User user;
public Token() {
ConverterLocalDateTime converter = new ConverterLocalDateTime();
loginTime = converter.convertToDatabaseColumn(LocalDateTime.now());
token = Double.toString(Math.random());
}
*getters and setters are not showed*
User entity
#Entity
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String password;
private String username;
//bi-directional one-to-one association to Employee
#OneToOne(mappedBy="user")
private Employee employee;
//bi-directional one-to-one association to Token
#OneToOne
#JoinColumn(name="tokID")
private Token token;
public User() {
}
*getters and setters are not showed*

Maybe I am missing something, but if your user ejb is meant to be bound to a single user, this is not the case, as a stateless can be reused for several other clients, and therefore the token will be reused along with the ooled instance. Check if this is the correct behavior.
Second, you cannot inject the tokens JPA entity or at least not with the current code, the variable would always be null. Maybe this is the reason you are not seeing it persisted.
Third, there are other things I would change, but it's another different question.

Related

Why is a field of my entity class null?

I have these two entities in a one to many relation:
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Short id;
#Basic(optional = false)
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "categoryId")
private Collection<Product> productCollection;
...
#XmlTransient
public Collection<Product> getProductCollection() {
return productCollection;
}
...
and
public class Product implements Serializable {
...
#JoinColumn(name = "category_id", referencedColumnName = "id")
#ManyToOne(optional = false)
private Category categoryId;
...
generated with NetBeans. The problem is that when the method getProductCollection() is called by the ControllerServlet the Collection of Product is null.
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userPath = request.getServletPath();
Category selectedCategory;
Collection<Product> categoryProducts;
// if category page is requested
if (userPath.equals("/category")) {
// get categoryId from request
String categoryId = request.getQueryString();
if (categoryId != null) {
// get selected category
selectedCategory = categoryFacade.find(Short.parseShort(categoryId));
// place selected category in request scope
request.setAttribute("selectedCategory", selectedCategory);
// get all products for selected category
categoryProducts = selectedCategory.getProductCollection();
// place category products in request scope
request.setAttribute("categoryProducts", categoryProducts);
}
Notice the null value of productCollection when other fields has been yet initialized
Edit 1: I declared the categoryFacade in the ControllerServlet applying the #EJB annotation
public class ControllerServlet extends HttpServlet {
#EJB
private CategoryFacade categoryFacade;
Edit 2: Here is the persistence.xml document
<?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="AffableBeanPU" transaction-type="JTA">
<jta-data-source>jdbc/affablebean</jta-data-source>
<properties/>
</persistence-unit>
</persistence>
Edit 3: I'm using TomEE 7.0.2
Try to initialize the Collection empty like:
#OneToMany(cascade = CascadeType.ALL, mappedBy = "categoryId")
private Collection<Product> productCollection = new HashSet<>();
Then you won't have null values even when there are no results in the lazy loaded relationship. If there are loaded values, they will be added to the collection.

JavaEE JPA synchronise object with database

I've got a User class and an Email class.
I used the #OneToMany annotatioin to describe a realationship that one user can have many emails and one email is assigned to one user.
Now the problem is: when creating a user and an email and assigning the email to the user, I try to find a way that the Set of emails is getting initialized by JPA. Usually this works fine when I am doing em.find(User.class, "test");
This only does not work when I'm creating a user. The emails attribute is always of size 0 or even null. But when I create a user, then redeploy my application and then execute em.find(User.class, "test"), the emails attribute is set correctly of size 1 and I can access it.
#Entity
public class User implements Serializable {
private String username;
private String password;
private Set<Email> emails;
#OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
public Set<Email> getEmails() {
return emails;
}
public void setEmails(Set<Email> emails) {
this.emails = emails;
}
#Id
#Column(name = "Username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#Basic
#Column(name = "Password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
-
#Entity
public class Email implements Serializable {
private int id;
private String email;
private User user;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "Id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#ManyToOne
#JoinColumn(name = "user")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Basic
#Column(name = "Email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
-
User user = new User();
user.setUsername("test");
user.setPassword("asdf");
em.persist(user);
Email e = new Email();
e.setEmail("test#test.com");
e.setUser(user);
em.persist(e);
return user;
after executing these statements, the user attribute emails is null (obviously). But strangely when I do em.find(User.class, "test"); in another method, the emails attribute is of size 0, even though the records are correctly inserted to the database.
When I now redeploy my application and call em.find(User.class, "test"); again, the emails attribute is of size 1.
I've already tried to call em.merge(); or em.refresh(); which did not work.
I am using glassfish 4.1.1. As transaction-type I use JTA and eclipselink for the JPA implementation
You need to add the email to the User as well and merge the user if you are doing it in two steps, or (you may need cascade=CascadeType.ALL) just put it in the User to begin with and persist the User if you are doing it in one step.
User user = new User();
Set<Email> emails = new HashSet<Email>();
user.setEmails(emails);
user.setUsername("test");
user.setPassword("asdf");
Email e = new Email();
e.setEmail("test#test.com");
e.setUser(user);
emails.add(e);
em.persist(user);
return user;
You need to set both sides of any bidirectional relationship, JPA will not do it for you. If you do not, the unset side will not reflect what is in the database until it is reloaded/refreshed from the database. You can force the refresh using em.refresh(user), but it is usually better to avoid the database hit and just add the email to the user's list of emails.

Spring Data Jpa Many to Many Query

entity :
Class User{
private String id;
#ManyToMany
private List<Role> roles;
}
Class Role{
private String id;
#ManyToMany(mappedBy = "roles")
private List<User> users;
}
UserRepository :
public interface UserRepository extends PagingAndSortingRepository<User, Serializable>{
#Query(" ??? ")
public User getUser(String id);
}
public class InMemorySecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(username -> {
com.casnetvi.cloud.domain.login.User employee = userRepository.findByEmail(username);
if (employee == null) {
throw new BadCredentialsException("User not found");
}
List<Role> roles1 = employee.getRoles();
System.out.println(roles1);
Print exception occurred :
failed to lazily initialize a collection of role: com.casnetvi.cloud.domain.login.User.roles, could not initialize proxy - no Session"
Want to find out what role(use the getRoles() method to get The Role object) , #Query how to write
( Not #Transactional , )
The default fetch type for manyToMany is Lazy.
so in order to get the list of roles you need to do one of the two :
1. execute the configure method inside a transaction.
2. set the relationship with EAGER fetch type:
#ManyToMany(fetch=FetchType.EAGER)
private List<Role> roles;

client PersistenceCapable NoClassDefFoundError while serializing Entity object from server to client using gwt

I'm using apache open JPA to access my db at the server side. I'm trying to call from my gwt client to the server in order to retrive an entity object, but this requests always fails with the error message:NoClassDefFoundError org/apache/openjpa/enhance/PersistenceCapable.
I tried defining my enhanced entity classes at the gwt.xml file and it did not helped:
<set-configuration-property name="rpc.enhancedClasses" value="com.jobsin.domain.SystemUser,com.jobsin.domain.Keyword,com.jobsin.domain.Job">/
My server function:
public SystemUser getCurrentUser()
throws InvalidUser{
HttpServletRequest httpServletRequest = this.getThreadLocalRequest();
HttpSession session = httpServletRequest.getSession();
SystemUser user=null;
Cookie[] cookies = httpServletRequest.getCookies();
SocialNetworkCookie cookie = network.generateCookieObject();
if(!cookie.init(cookies)){
session.invalidate();
throw new InvalidUser(); // no user was connected, user need to login
}
//try get user details from db
EntityManager em = factory.createEntityManager();
SystemUserDAOImpl userdao = new SystemUserDAOImpl(em);
user = userdao.findUserByNetworkId(cookie.getMemberId());
//make user detach
em.close();
return user;
}
SystemUser Class :
#Entity
public class SystemUser implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -1673271845552139219L;
#Id
#GeneratedValue
private long id;
#NotNull
private String firstName;
#NotNull
private String lastName;
#NotNull
#Column(unique=true)
private String email;
#Temporal(TemporalType.TIMESTAMP)
private Date lastSearch;
#ManyToMany(cascade = CascadeType.ALL)
private Set<Job> jobs = new HashSet<Job>();
#ManyToMany(cascade = CascadeType.ALL)
private Set<Keyword> keywords = new HashSet<Keyword>();
}
The easiest solution would be to add the OpenJPA binaries to the GWT client classpath.

Object: entity.ENTITY[ id=null ] is not a known entity type

this is a similar post to one I have seen before regarding this exception but I am utterly lost. I have yet to persist an entity to a database using JPA, although I have read from tables using it no problem. My setup is Netbeans 7.1 using Glassfish 3.1.1, EclipseLink is my persistence provider. I have a very simple scenario where I just want to test writing a persons name and age into the database and having the id auto increment. Its an MySql database with the fields: Id, FirstName and Age. Heres my code:
Web servlet to take in name and age from html form:
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userPath = request.getServletPath();
if(userPath.equals("/addUser")){
//get request parameters from form
String name = request.getParameter("name");
String age = request.getParameter("age");
//set request attributes to be used by forwarded page
request.setAttribute("name", name);
request.setAttribute("age", age);
//create manager class to add person to database
Manager manager = new Manager();
manager.addPerson(name, age);
userPath = "/result";
}
// use RequestDispatcher to forward request internally
String url = "/WEB-INF/view" + userPath + ".jsp";
try {
request.getRequestDispatcher(url).forward(request, response);
} catch (Exception ex) {
ex.printStackTrace();
}
}
Manager class that takes in name and age, creates a person object and persists it.
public class Manager {
private static final String PERSISTENCE_UNIT_NAME = "FormPU";
private static EntityManagerFactory factory;
public Manager() {
}
public void addPerson(String name, String age) {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
Persons persons = new Persons();
persons.setName(name);
persons.setAge(age);
em.getTransaction().begin();
em.persist(persons);
em.getTransaction().commit();
em.close();
}
}
Persons entity class:
/**
*
* #author esmiala
*/
#Entity
#Table(name = "persons")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Persons.findAll", query = "SELECT p FROM Persons p"),
#NamedQuery(name = "Persons.findById", query = "SELECT p FROM Persons p WHERE
p.id = :id"),
#NamedQuery(name = "Persons.findByFirstName", query = "SELECT p FROM Persons p
WHERE p.firstName = :firstName"),
#NamedQuery(name = "Persons.findByAge", query = "SELECT p FROM Persons p WHERE
p.age = :age")})
public class Persons implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(name = "Id")
private Integer id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 255)
#Column(name = "FirstName")
private String firstName;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 255)
#Column(name = "Age")
private String age;
public Persons() {
}
public Persons(Integer id) {
this.id = id;
}
public Persons(Integer id, String firstName, String age) {
this.id = id;
this.firstName = firstName;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
#Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Persons)) {
return false;
}
Persons other = (Persons) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
#Override
public String toString() {
return "entity.Persons[ id=" + id + " ]";
}
}
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="FormPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/form</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
Note: I have also tried setting exclude-unlisted-classes tag to true and list the class seperately but that didn't work either.
The exception:
WARNING: StandardWrapperValve[Controller]: PWC1406: Servlet.service() for servlet
Controller threw exception
java.lang.IllegalArgumentException: Object: entity.persons[ id=null ] is not a
known entity type.
atorg.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObject
ForPersist(UnitOfWorkImpl.java:4141)
atorg.eclipse.persistence.internal.jpa.EntityManagerImpl.
persist(EntityManagerImpl.java:368)
at manager.Manager.addPerson(Manager.java:36)
at controller.Controller.doPost(Controller.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
...and so on. Any help would be greatly appreciated!
<exclude-unlisted-classes> doesn't work as you would expect - the very presence of this element in persistence.xml disables automatic discovery of #Entity classes, no matter what's inside it.
Also, #Entity(name="persons") is probably not what you want, use #Entity #Table (name="persons") instead.
So you say you can read the class fine, but get an error persisting a new instance?
Can you update an object that you read?
It seems you are having some kind of class loader issue. Somehow you have the class on your classpath twice, or have two different class loaders. The object you are passing to persist is from a different class loader than the one JPA is using. You can check the class loader of what was read, and of the object being persisted to see how they differ.
Have you redeployed you app, or hotdeployed? Does it work if you shut down/restart the server properly. Ensure you are closing your old EntityManagerFactory before redeploying.
Concerning youe concrete problem, try to see if this link helps.
Anyway, the way you are instantiating the EntityManager is not thread safe.
You can see here why. Or, better, you can use NetBeans' wizard for creating JPA controller classes from entity classes, and see how it injects the EntityManager:
#PersistenceContext
private EntityManager em;
See also that the controller classes (the equivalent of your Manager POJO) have the Stateless annotation. This is because you can safely inject an EJB (in this case the EntityManager) only in an object whose lifecycle is managed by the web container (see here for further reference about Accessing Enterprise Beans).