Persistence unit exception - java

i've this problem with my Enterprise Java Bean.
Log file:
stack trace
I don't know how to resolve it! This is my Entity class:
package entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
*
* #author gfucc
*/
#Entity
#NamedQueries({
#NamedQuery(name = "Student.findAll", query = "SELECT s FROM Students"),
#NamedQuery(name = "Student.findByMatr", query = "SELECT s FROM Student s WHERE s.matricola = :matricola"),
#NamedQuery(name = "Student.findByCognome", query = "SELECT s FROM Student s WHERE s.cognome = :cognome")
})
public class Student
{
#Id #GeneratedValue
private String matricola;
#NotNull
#Column(length = 100)
private String nome;
#NotNull
#Column(length = 100)
private String cognome;
#NotNull
#Column(length = 100)
private String corsoLaurea;
#NotNull
#Size(min = 0, max = 30)
private int numEsamiSostenuti;
public Student()
{
}
public Student(String nome, String cognome, String corsoLaurea, int numEsamiSostenuti) {
this.nome = nome;
this.cognome = cognome;
this.corsoLaurea = corsoLaurea;
this.numEsamiSostenuti = numEsamiSostenuti;
}
public String getMatricola() {
return matricola;
}
public void setMatricola(String matricola) {
this.matricola = matricola;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getCognome() {
return cognome;
}
public void setCognome(String cognome) {
this.cognome = cognome;
}
public String getCorsoLaurea() {
return corsoLaurea;
}
public void setCorsoLaurea(String corsoLaurea) {
this.corsoLaurea = corsoLaurea;
}
public int getNumEsamiSostenuti() {
return numEsamiSostenuti;
}
public void setNumEsamiSostenuti(int numEsamiSostenuti) {
this.numEsamiSostenuti = numEsamiSostenuti;
}
#Override
public String toString() {
return "Student{" +
"matricola=" + matricola +
", nome=" + nome +
", cognome=" + cognome +
", corsoLaurea=" + corsoLaurea +
", numEsamiSostenuti=" + numEsamiSostenuti + '}';
}
}
This is my EJB:
package ejbs;
import entities.Student;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import qualifiers.Loggable;
/**
*
* #author gfucc
*/
#Stateless
#Loggable
public class StudentEJB implements StudentEJBRemote
{
#PersistenceContext(unitName = "StudentEJBPU")
private EntityManager em;
#Override
public Student createStudent(Student student)
{
em.persist(student);
return this.getStudentByMatricola(student.getMatricola());
}
#Override
public Student removeStudent(Student student)
{
Student toReturn = this.getStudentByMatricola(student.getMatricola());
if(toReturn != null)
{
em.remove(student);
return toReturn;
}
return null;
}
#Override
public Student updateStudent(Student student)
{
return em.merge(student);
}
#Override
public List<Student> getStudentList()
{
TypedQuery<Student> query = em.createNamedQuery("Student.findAll", Student.class);
return query.getResultList();
}
#Override
public Student getStudentByMatricola(String matricola)
{
TypedQuery<Student> query = em.createNamedQuery("Student.findByMatr", Student.class);
query.setParameter(1, matricola);
return query.getSingleResult();
}
#Override
public Student getStudentByCognome(String cognome)
{
TypedQuery<Student> query = em.createNamedQuery("Student.findByCognome", Student.class);
query.setParameter(1, cognome);
return query.getSingleResult();
}
}
This is 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="StudentEJBPU" transaction-type="JTA">
<jta-data-source>jdbc/sample</jta-data-source>
<class>entities.Student</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
This is my beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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"
bean-discovery-mode="all">
</beans>
Now in these images you can see my project structure:
project structure
What is the problem? I've all. The database i connected, i used a default database "sample"... The problem is on the persistence unit because without it i can build and then deploy without problem! Please help. Thanks a lot

Related

Cannot find the declaration of element 'persistence' JPA and hibernate provider

I am new in jpa and I am tryingg to write and execute a sample founded here:Sample JPA
This is my table created:
Here is my persistance.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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_0.xsd">
<persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>ir.ac.sbu.testsimplesql1.Employee</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/library?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.password" value="pass"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hbm2ddl.auto" value="update"/>
</properties>
I have auto generate model class from database:
package ir.ac.sbu.testsimplesql1;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
#Entity
#Table(name = "Employee")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e"),
#NamedQuery(name = "Employee.findById", query = "SELECT e FROM Employee e WHERE e.id = :id"),
#NamedQuery(name = "Employee.findByFistName", query = "SELECT e FROM Employee e WHERE e.fistName = :fistName"),
#NamedQuery(name = "Employee.findByLastName", query = "SELECT e FROM Employee e WHERE e.lastName = :lastName"),
#NamedQuery(name = "Employee.findByDept", query = "SELECT e FROM Employee e WHERE e.dept = :dept")})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "fistName")
private String fistName;
#Column(name = "lastName")
private String lastName;
#Column(name = "dept")
private String dept;
public Employee() {
}
public Employee(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFistName() {
return fistName;
}
public void setFistName(String fistName) {
this.fistName = fistName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
#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 Employee)) {
return false;
}
Employee other = (Employee) 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 "ir.ac.sbu.testsimplesql1.Employee[ id=" + id + " ]";
}
}
This is my poem.xml: (Dependencies Tag)
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.8.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.2</version>
</dependency>
</dependencies>
And the last thing is my main function:
public class EmployeeTest {
private static EntityManager em;
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeeService");
em = emf.createEntityManager();
createEmployee(1, "Saint", "Peter", "Engineering");
createEmployee(2, "Jack", " Dorsey", "Imaginea");
createEmployee(3, "Sam", "Fox", "Imaginea");
}
private static void createEmployee(int id, String firstName, String lastName, String dept) {
em.getTransaction().begin();
Employee emp = new Employee();
emp.setId(id);
emp.setFistName(firstName);
emp.setLastName(lastName);
emp.setDept(dept);
em.persist(emp);
em.getTransaction().commit();
}
}
But when I run this code I face with this error:
I have searched this error bud couldn't understand what should I do. I've also visited this link:
Can not find the declaration of element 'persistence'
javax.persistence.PersistenceException - JPA+Hibernate
and alot more similar questions ....
Can anyone please help me to solve this error?
Thanks in advance for your attention.
You can check your XML against the XSD here : http://www.freeformatter.com/xml-validator-xsd.html
Very useful.
Replace the beginning of your xml with:
<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">
I don't know why, but yours is not validated.
Also, you miss the end of the xml, but i guess it's just a copy/paste error.

JPA 2.0 not persisting into MySQL

I am new to JPA 2.0 API and I am trying to have a start up with JPA to Mysql transaction but I am enable to do so. And I am not getting any errors.
package com.testjpa.demo;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the employee database table.
*
*/
#Entity
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
public Employee() {
}
public Employee(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
Methods to perform CRUD operations
package com.testjpa.demo;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
public class EmployeeService {
/**
* #param args
*/
protected EntityManager em;
public EmployeeService(EntityManager em) {
this.em = em;
}
public Employee findEmployee(int id) {
return em.find(Employee.class, id);
}
public Employee createEmployee(int id, String name) {
Employee emp = new Employee(id);
emp.setName(name);
return emp;
}
public void removeEmployee(int id) {
Employee emp = findEmployee(id);
if (emp != null) {
em.remove(emp);
}
}
public List<Employee> findAllEmployees() {
TypedQuery<Employee> query = em.createQuery("select e from Employee e",
Employee.class);
return query.getResultList();
}
}
Test Class to persist the data into MysQL
package com.testjpa.demo;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class EmployeeTest {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("JPADemo");
EntityManager em = emf.createEntityManager();
EmployeeService service = new EmployeeService(em);
// create and persist an employee
em.getTransaction().begin();
Employee emp = service.createEmployee(2, "John Doe");
em.getTransaction().commit();
System.out.println("Persisted " + emp);
emp = service.findEmployee(2);
System.out.println("Found " + emp);
}
}
I will really appreciate suggestions as i am totally new to this API
Also 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="JPADemo" transaction-type="RESOURCE_LOCAL">
<class>com.testjpa.demo.Employee</class>
<properties>
<property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/world"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123456"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>
</persistence>
In your createEmployee method you are instantiating a new Employee POJO but you never persist it with the EntityManager, so Hibernate is not aware of it. Try adding:
em.persist(emp);

Junit test doesn't persist entity with Google App Engine

I'm developing a project using GAE. I'm writing an integration test with Junit which don't save the entity. I have included the JARs in classpath and I copy here the entity class, the test class and the persistence.xml file.
Persistence.xml
<?xml version="1.0" encoding="UTF-8" ?>
<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_1_0.xsd" version="1.0">
<persistence-unit name="transactions-optional">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<properties>
<property name="datanucleus.NontransactionalRead" value="true"/>
<property name="datanucleus.NontransactionalWrite" value="true"/>
<property name="datanucleus.ConnectionURL" value="appengine"/>
</properties>
</persistence-unit>
</persistence>
Utente.java
package it.bfm.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.google.appengine.api.datastore.Key;
#Entity
public class Utente {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
private Key key;
private String nome;
private String cognome;
private String username;
private String password;
private String email;
public Utente(String nome, String cognome, String user, String password,
String email){
this.nome = nome;
this.cognome = cognome;
this.username = user;
this.password = password;
this.email = email;
}
public Key getKey(){
return this.key;
}
public void setNome(String nome){
this.nome = nome;
}
public String getNome(){
return this.nome;
}
public void setCognome(String cognome){
this.cognome = cognome;
}
public String getCognome(){
return this.cognome;
}
public void setUser(String username){
this.username = username;
}
public String getUsername(){
return this.username;
}
public void setPassword(String password){
this.password = password;
}
public String getPasswrd(){
return this.password;
}
public void setEmail(String email){
this.email = email;
}
public String getEmail(){
return this.email;
}
}
UtenteTest.java
package it.bfm.test;
import it.bfm.business.UtenteImpl;
import it.bfm.business.UtenteInterface;
import it.bfm.entity.Utente;
import java.util.List;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import junit.framework.TestCase;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
public class UtenteTest extends TestCase{
private final static LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
private static UtenteInterface utImpl = new UtenteImpl();
#BeforeClass
public static void setUpUtenti() {
utImpl.creaUtente("Utente1", "Test1", "test1", "test1", "test1#test.it");
utImpl.creaUtente("Utente2", "Test2", "test2", "test2", "test2#test.it");
utImpl.creaUtente("Utente3", "Test3", "test3", "test3", "test3#test.it");
}
#Before
public void setUp(){
helper.setUp();
}
#After
public void tearDown() {
helper.tearDown();
}
#Test
public void testCreaUtente() {
utImpl.creaUtente("Utente4", "Test4", "test4", "test4", "test4#test.it");
}
#Test
public void testListaUtenti() {
List<Utente> utenti = null;
utenti = utImpl.listaUtenti();
Assert.assertEquals(4, utenti.size());
}
#Test
public void testCercaUtenteByEmail() {
Utente utente;
String emailTest = "test1#test.it";
String nomeTest = "Utente1";
String cognomeTest = "Test1";
utente = utImpl.cercaUtenteByEmail(emailTest);
Assert.assertEquals(utente.getNome(), nomeTest);
Assert.assertEquals(utente.getCognome(), cognomeTest);
}
#Test
public void testLogin() {
Utente utente;
String usernameTest = "test1";
String passTest = "test1";
String nomeTest = "Utente1";
String cognomeTest = "Test1";
utente = utImpl.login(usernameTest, passTest);
Assert.assertEquals(utente.getNome(), nomeTest);
Assert.assertEquals(utente.getCognome(), cognomeTest);
}
}
The problem is that the methods setUpUtenti ad testCreaUtente don't persist the entities.
The test testListaUtenti fails because the Utenti numbers was expected 4 but is 0.
Every #Test annotated method is invoked on a freshly created instance of class. So basically you can not persist between methods. You should put this code into one method.

How can I use put method to insert data to my MySQL databse using restful webservice

I use this tutorrial and I created this
table (id ,username) prints;
and now I want to insert data to it using the restful web service
what should I put in the content text box to do that ?
this is my paints class
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package entities;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* #author subhi
*/
#Entity
#Table(name = "prints")
#XmlRootElement(name = "prints")
#NamedQueries({
#NamedQuery(name = "Prints.findAll", query = "SELECT p FROM Prints p"),
#NamedQuery(name = "Prints.findById", query = "SELECT p FROM Prints p WHERE p.id = :id"),
#NamedQuery(name = "Prints.findByUsername", query = "SELECT p FROM Prints p WHERE p.username = :username")})
public class Prints implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 30)
#Column(name = "username")
private String username;
public Prints() {
}
public Prints(Integer id) {
this.id = id;
}
public Prints(Integer id, String username) {
this.id = id;
this.username = username;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#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 Prints)) {
return false;
}
Prints other = (Prints) 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 "entities.Prints[ id=" + id + " ]";
}
}
I tried use put method but I got this error
and why I didn't have post method in combobox?
controller code java EE 6
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package service;
import entities.Prints;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.netbeans.saas.RestResponse;
import org.netbeans.saas.google.GoogleMapService;
/**
*
* #author subhi
*/
#Stateless
#Path("entities.prints")
public class PrintsFacadeREST extends AbstractFacade<Prints> {
#PersistenceContext(unitName = "test3PU")
private EntityManager em;
public PrintsFacadeREST() {
super(Prints.class);
}
#POST
#Override
#Consumes({"application/xml", "application/json"})
public void create(Prints entity) {
super.create(entity);
}
#PUT
#Override
#Consumes({"application/xml", "application/json"})
public void edit(Prints entity) {
super.edit(entity);
}
#DELETE
#Path("{id}")
public void remove(#PathParam("id") Integer id) {
super.remove(super.find(id));
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public Prints find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Override
#Produces({"application/xml", "application/json"})
public List<Prints> findAll() {
return super.findAll();
}
#GET
#Path("{from}/{to}")
#Produces({"application/xml", "application/json"})
public List<Prints> findRange(#PathParam("from") Integer from, #PathParam("to") Integer to) {
return super.findRange(new int[]{from, to});
}
#GET
#Path("count")
#Produces("text/plain")
public String countREST() {
return String.valueOf(super.count());
}
#Override
protected EntityManager getEntityManager() {
return em;
}
#GET
#Produces("text/html")
public String getGoogleMap() {
// Drag and drop the getGoogleMap operation here
try {
String address = "16 Network Circle, Menlo Park";
java.lang.Integer zoom = 15;
String iframe = "false";
RestResponse result = GoogleMapService.getGoogleMap(address, zoom, iframe);
return result.getDataAsString();
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
}
Put the request body part there.If you going to update some entity then you should pass the dto with data which should be updated.I didn't go through your link.this part can be in Json or XML.(like below)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<prints>
<id>1</id>
<username>test</username>
</prints>
you have to annotate your dto lets say printsDTO as below
#XmlRootElement(name = "prints")
public class PrintsDTO {
private int id;
private String username;
// have getters and setteres for above
}
I used code to insert data to my restful web service using restful client application as follow
NewJerseyClient client = new NewJerseyClient();
Prints p = new Prints();
p.setId(235);
p.setUsername("subhi");
client.create_XML(p);
and this is sufficient for my case

My EJB throws a transaction required exception although another EJB setup in the same way with same persistence unit throws no excpetion

First here is my entire EJB file:
package enkia.pulse.indexing.beans;
import enkia.pulse.core.Category;
import enkia.pulse.core.Product;
import enkia.pulse.core.Review;
import enkia.pulse.core.Twitter;
import enkia.utils.HarvestingConstants;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;
import twitter4j.FilterQuery;
import twitter4j.Status;
import twitter4j.StatusDeletionNotice;
import twitter4j.StatusListener;
import twitter4j.TwitterException;
import twitter4j.TwitterStream;
import twitter4j.TwitterStreamFactory;
import twitter4j.auth.AccessToken;
/**
*
* #author joshua
*/
#Stateless
public class TwitterBean implements TwitterBeanLocal,
TimedObject {
List<String> _twitterTopics;
Map<String,Integer> _tagCatRel;
TimerService _timerService;
Timer _timer;
/** The session context needed to create the timer */
#Resource
private SessionContext _sc;
#PersistenceContext(unitName=HarvestingConstants.PERSISTENCE_UNIT)
EntityManager _entityManager;
/** A logging object for formatted output to the server log. */
private Logger _logger;
private int errors;
/**
* Constructs the logger
*/
public TwitterBean(){
_logger = Logger.getLogger(this.getClass().getName());
_logger.log(Level.INFO,"Instantiating Twitter Bean");
}
/**
* Attempts to retrieve the configuration object. Creates the harvester
* with the configuration and then sets a timer to run the harvester
* periodically
*/
public void initialize() {
_logger.log(Level.INFO,"Initializing Twitter bean.");
_twitterTopics = new LinkedList<String>();
_tagCatRel = new HashMap<String,Integer>();
_timerService = _sc.getTimerService();
_timer = _timerService.createTimer(0,1000*60*60,null); //restart every hour
_logger.log(Level.INFO,"Starting Twitter timer");
}
public void ejbTimeout(Timer timer) {
_logger.log(Level.INFO,"Running Twitter timer");
findTopics();
try {
setupStream();
} catch (TwitterException ex) {
Logger.getLogger(TwitterBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void setupStream() throws TwitterException{
StatusListener listener = new StatusListener(){
#Override
public void onStatus(Status status) {
insertStatus(status);
}
#Override
public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
//DO nothing
}
#Override
public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
_logger.log(Level.INFO,"Track limitation notice: "+numberOfLimitedStatuses);
}
#Override
public void onScrubGeo(long l, long l1) {
_logger.log(Level.INFO,"Scrub GEO");
}
#Override
public void onException(Exception ex) {
ex.printStackTrace();
}
};
TwitterStream twitterStream = new TwitterStreamFactory().getInstance();
twitterStream.setOAuthConsumer("secret", "secret");
twitterStream.setOAuthAccessToken(new AccessToken("secret","secret"));
FilterQuery query = new FilterQuery();
query = query.track(_twitterTopics.toArray(new String[_twitterTopics.size()]));
twitterStream.addListener(listener);
twitterStream.filter(query);
}
public void insertStatus(Status status){
String foundTag="";
for(String tag : _tagCatRel.keySet()){
if(status.getText().toLowerCase().contains(tag.toLowerCase())){
//found
foundTag=tag;
break;
}
}
if(foundTag.equals("")){
return;
}
Integer category = _tagCatRel.get(foundTag);
Query q=_entityManager.createNamedQuery("Category.findByCategoryId");
q.setParameter("categoryId",category);
Category c = (Category) q.getSingleResult();
Product p = new Product(c);
_entityManager.persist(p);
_entityManager.merge(p);
Review r = new Review();
r.setReview(status.getText());
r.setUrl("http://www.twitter.com/"+status.getUser().getScreenName()+"/statuses/"+status.getId());
r.setProcessed(0);
r.setDateCreated(status.getCreatedAt().getTime());
p.getPartNumber();
r.setProductId(p.getProductId());
_entityManager.persist(r);
_logger.log(Level.INFO,"Added tweet:" + r.getReview());
}
private void findTopics() {
_twitterTopics = new LinkedList<String>();
Query twitterQuery=_entityManager.createNamedQuery("Twitter.findAll");
String all="";
for(Object t: twitterQuery.getResultList()){
Twitter twitter=(Twitter) t;
for(String tag : twitter.getTags().split(" ")){
_twitterTopics.add(tag);
all+=tag+", ";
Integer test = twitter.getCategoryId();
_tagCatRel.put(tag,twitter.getCategoryId());
}
}
_logger.log(Level.INFO,"Tracking: "+all);
}
}
And my persistence.xml:
<?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="PulsePU" transaction-type="JTA">
<jta-data-source>pulseEJB</jta-data-source>
<class>enkia.pulse.core.Category</class>
<class>enkia.pulse.core.Department</class>
<class>enkia.pulse.core.Feature</class>
<class>enkia.pulse.core.Product</class>
<class>enkia.pulse.core.Review</class>
<class>enkia.pulse.core.ReviewSnippet</class>
<class>enkia.pulse.core.Sentiment</class>
<class>enkia.pulse.core.SentimentReview</class>
<class>enkia.pulse.core.Twitter</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
Lastly is my sun-resource.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Resource Definitions //EN" "http://www.sun.com/software/appserver/dtds/sun-resources_1_3.dtd">
<resources>
<jdbc-resource enabled="true" jndi-name="pulseEJB" object-type="user" pool-name="mysqlPool"/>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="mysqlPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="endpoint"/>
<property name="portNumber" value="3306"/>
<property name="databaseName" value="pulse"/>
<property name="User" value="user"/>
<property name="Password" value="password"/>
<property name="URL" value="jdbc:mysql://endpoint/pulse"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
I'm using Netbeans.
I instantiate my EJB in a webproject. I have another EJB setup the same that I instantiate there that works fine with container managed transaction. I also tried just saying "screw it" and used UserTransaction but that had problems with the merge and ended up with numerous unexpected problems, NPE on p right after "_entityManager.persist(p); _entityManager.merge(p);"
Any suggestions on where to look for differences between the two EJBs is appreciated as I'm out of ideas.
I also noticed netbeans is generating sources for two of my entity classes in the problematic EJB labeled "ap-source-output" but doesn't in the working EJB.
Generated Code I don't understand why being generated below:
package enkia.pulse.core;
import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
#Generated(value="EclipseLink-2.2.0.v20110202-r8913", date="2012-08-08T23:09:05")
#StaticMetamodel(Twitter.class)
public class Twitter_ {
public static volatile SingularAttribute<Twitter, Integer> id;
public static volatile SingularAttribute<Twitter, String> tags;
public static volatile SingularAttribute<Twitter, Integer> categoryId;
public static volatile SingularAttribute<Twitter, Long> lastStatus;
}
And
package enkia.pulse.core;
import enkia.pulse.core.Category;
import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
#Generated(value="EclipseLink-2.2.0.v20110202-r8913", date="2012-08-08T23:41:31")
#StaticMetamodel(Product.class)
public class Product_ {
public static volatile SingularAttribute<Product, String> productBrand;
public static volatile SingularAttribute<Product, Category> category;
public static volatile SingularAttribute<Product, String> model;
public static volatile SingularAttribute<Product, byte[]> image;
public static volatile SingularAttribute<Product, String> productName;
public static volatile SingularAttribute<Product, String> imageURL;
public static volatile SingularAttribute<Product, String> specifications;
public static volatile SingularAttribute<Product, Integer> productId;
public static volatile SingularAttribute<Product, String> partNumber;
}
While I'm at it I'll show the entity file too:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package enkia.pulse.core;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
/**
*
* #author fbarrow
*/
#Entity
#Table(name = "twitter")
#NamedQueries({
#NamedQuery(name = "Twitter.findAll", query = "SELECT t FROM Twitter t"),
#NamedQuery(name = "Twitter.findById", query = "SELECT t FROM Twitter t WHERE t.id = :id"),
#NamedQuery(name = "Twitter.findByCategoryId", query = "SELECT t FROM Twitter t WHERE t.categoryId = :categoryId"),
#NamedQuery(name = "Twitter.findByTags", query = "SELECT t FROM Twitter t WHERE t.tags = :tags"),
#NamedQuery(name = "Twitter.findByLastStatus", query = "SELECT t FROM Twitter t WHERE t.lastStatus = :lastStatus")})
public class Twitter implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "categoryId")
private Integer categoryId;
#Column(name = "tags")
private String tags;
#Column(name = "lastStatus")
private Long lastStatus;
public Twitter() {
}
public Twitter(Integer id) {
this.id = id;
}
public Twitter(Integer id, Integer categoryId, String tags, Long lastStatus) {
this.id = id;
this.categoryId = categoryId;
this.tags = tags;
this.lastStatus = lastStatus;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getCategoryId() {
return categoryId;
}
public void setCategoryId(Integer categoryId) {
this.categoryId = categoryId;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public Long getLastStatus() {
return lastStatus;
}
public void setLastStatus(Long lastStatus) {
this.lastStatus = lastStatus;
}
#Override
public int hashCode() {
Integer 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 Twitter)) {
return false;
}
Twitter other = (Twitter) 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 "enkia.pulse.core.Twitter[ id=" + id + " ]";
}
}
Error:
SEVERE: javax.persistence.TransactionRequiredException
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:263)
at enkia.pulse.indexing.beans.TwitterBean.insertStatus(TwitterBean.java:154)
at enkia.pulse.indexing.beans.TwitterBean$1.onStatus(TwitterBean.java:99)
at twitter4j.StatusStreamImpl.onStatus(StatusStreamImpl.java:78)
at twitter4j.AbstractStreamImplementation$1.run(AbstractStreamImplementation.java:107)
at twitter4j.internal.async.ExecuteThread.run(DispatcherImpl.java:114)
Use of Timer to create TwitterStream, running an independent thread?
The timer calls setupStream, which creates a listener, and binds that listener to twitterStream, created via the TwitterStreamFactory. That code isn't shown, however from the context it would appear that the TwitterStream is running code asynchronously:
twitter4j.internal.async.ExecuteThread
is in your stack-trace, below the exception. My bet is you're managing your own threads, which is not running within the container's context - all bets are off for accessing container resources and interacting with the container in this model (which is why Java EE so strongly suggests that you do NOT run your own threading model).
Specifically, that code is NOT running within a container managed transaction.
You might explore having the the Timer Service launch the background task via an MDB, which will run asynchronously from your EJB, in a proper container.

Categories