EJJB Timer Transaction -XA Exception - jpa

I am using EJB 3.0 timer.When my Timeout method gets invoked,I use JPA to insert a record in one of the table.I use JPA to persist the data.I defined the persist code in a Stateless Session Bean and invoked the local interface inside my timeout method.I get the following exception when the thread comes out of the timeout method:
javax.transaction.xa.XAException: JDBC driver does not support XA, hence cannot be a participant in two-phase commit.
To force this participation, set the GlobalTransactionsProtocol attribute to LoggingLastResource (recommended) or EmulateTwoPhaseCommit for the Data Source
Our DB does not support XA transaction.We use WL 10.3.1.Here is the code which i do :
#EJB
private MyejbLocal myejbLocal
#Timeout
public void callEjb(timer) {
try {
myejbLocal .store();
} catch (EntityExistsException e) {
e.getMessage();
} catch (Exception ex) {
ex.getCause();
}
}
Here is my implementation:
#Override
public void Store() {
try {
Mytable mytable= new Mytable (new Date());
persist(mytable);
} catch (EntityExistsException e) {
e.getMessage();
} catch (Exception ex) {
ex.getCause();
}
}
I don't call flush() method.
Please let me know if I have missed any?

I also faced the same issue. You need to keep your JPA entity operation in a separate session bean and it will work.
http://prasunejohn.blogspot.in/2014/02/understanding-ejb-timer-service-31.html

Related

#Transactional with handling error and db-inserts in catch block (Spring Boot)

I would like to rollback a transaction for the data in case of errors and at the same time write the error to db.
I can't manage to do with Transactional Annotations.
Following code produces a runtime-error (1/0) and still writes the data into the db. And also writes the data into the error table.
I tried several variations and followed similar questions in StackOverflow but I didn't succeed to do.
Anyone has a hint, how to do?
#Service
public class MyService{
#Transactional(rollbackFor = Exception.class)
public void updateData() {
try{
processAndPersist(); // <- db operation with inserts
int i = 1/0; // <- Runtime error
}catch (Exception e){
persistError()
trackReportError(filename, e.getMessage());
}
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void persistError(String message) {
persistError2Db(message); // <- db operation with insert
}
You need the way to throw an exception in updateData() method to rollback a transaction. And you need to not rollback persistError() transaction at the same time.
#Transactional(rollbackFor = Exception.class)
public void updateData() {
try{
processAndPersist(); // <- db operation with inserts
int i = 1/0; // <- Runtime error
}catch (Exception e){
persistError()
trackReportError(filename, e.getMessage());
throw ex; // if throw error here, will not work
}
}
Just throwing an error will not help because persistError() will have the same transaction as updateData() has. Because persistError() is called using this reference, not a reference to a proxy.
Options to solve
Using self reference.
Using self injection Spring self injection for transactions
Move the call of persistError() outside updateData() (and transaction). Remove #Transactional from persistError() (it will not work) and use transaction of Repository in persistError2Db().
Move persistError() to a separate serface. It will be called using a proxy in this case.
Don't use declarative transactions (with #Transactional annotation). Use Programmatic transaction management to set transaction boundaries manually https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch11s06.html
Also keep in mind that persistError() can produce error too (and with high probability will do it).
Using self reference
You can use self reference to MyService to have a transaction, because you will be able to call not a method of MyServiceImpl, but a method of Spring proxy.
#Service
public class MyServiceImpl implements MyService {
public void doWork(MyService self) {
DataEntity data = loadData();
try {
self.updateData(data);
} catch (Exception ex) {
log.error("Error for dataId={}", data.getId(), ex);
self.persistError("Error");
trackReportError(filename, ex);
}
}
#Transactional
public void updateData(DataEntity data) {
persist(data); // <- db operation with inserts
}
#Transactional
public void persistError(String message) {
try {
persistError2Db(message); // <- db operation with insert
} catch (Exception ex) {
log.error("Error for message={}", message, ex);
}
}
}
public interface MyService {
void doWork(MyService self);
void updateData(DataEntity data);
void persistError(String message);
}
To use
MyService service = ...;
service.doWork(service);

EntityManager in Transactional CDI bean

I have an EntityManager associated with my persistence unit (myPU).
I have the following code which represents a generic DataAccessObject which I want to use in order to execute tasks in a new transaction (requires-new).
This DataAccessObject gets injected into an EJB and its unique method gets invoked in a while loop.
Another EntityManager instance referencing the same persistence unit exists in the EJB.
I'm expecting that at every method invocation of my DataAccessObject instance, a new transaction gets created and committed (or rollbacked) according to the following code.
The problem is that i get a transaction required exception. What am i missing?
#Dependent
#ManagedBean
public class DataAccessObject {
private static final Logger logger = Logger.getLogger(DataAccessObject.class);
#PersistenceContext(unitName = "scheduler")
private EntityManager entityManager;
#Transactional(value = TxType.REQUIRES_NEW, rollbackOn = Exception.class)
public void executeInNewTransaction(TransactionalTask transactionalTask) throws TransactionalException {
Throwable exception = null;
try {
logger.debug(" A new transaction has been created for transactional task: \"", transactionalTask, "\".");
transactionalTask.onExecute(entityManager);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
exception = e;
} catch (ConstraintViolationException e) {
Set<ConstraintViolation<?>> constraintViolation = e.getConstraintViolations();
logger.error("Exception during bean validation:");
if (constraintViolation != null) {
for (ConstraintViolation<?> violation : constraintViolation) {
logger.error(String.format("%s=\"%s\" error: %s", violation.getPropertyPath(), violation.getInvalidValue(), violation.getMessage()));
}
}
exception = e;
} catch (Throwable e) {
exception = e;
} finally {
if (exception != null || transactionalTask.mustRollBack()) {
throw new TransactionRolledBackException("Transaction is being rolled back for transactional task: \"" + transactionalTask + "\".", exception);
} else {
logger.debug(" Transaction has been committed successfully for transactional task: \"", transactionalTask, "\".");
}
}
}
}

No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call, Exception

Have a list of data need to be saved. Before the save had to delete the existing data and save the new data.
If any of the delete & save is failed that transaction need to roll back, rest of the delete & save transaction should continue.
public LabResResponse saveLabResult(List<LabResInvstResultDto> invstResults) {
LabResResponse labResResponse = new LabResResponse();
List<Long> relInvstid = new ArrayList<Long>();
try{
if(invstResults != null){
List<LabResInvstResult> labResInvstResults = mapper.mapAsList(invstResults, LabResInvstResult.class);
for(LabResInvstResult dto: labResInvstResults){
if(dto != null){
//delete all child records before save.
deleteResult(dto, relInvstid);
}
}
}
labResResponse.setRelInvstids(relInvstid);
}catch(Exception e){
e.printStackTrace();
}
return labResResponse;
}
Here new transaction will added for each delete & save
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = { Exception.class })
private void deleteResult(LabResInvstResult dto, List<Long> relInvstid) {
try{
labResultRepo.deleteById(dto.getId());
LabResInvstResult result = labResultRepo.save(dto);
}catch(Exception e){
e.printStackTrace();
}
}
On delete it throws an exception "Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call"
I can solve this by adding a #Transactional for public LabResResponse saveLabResult(List invstResults) method.
But my intial usecase will not work this will roll back entire list of transaction.
Here are two problems.
The first problem is that you call the "real" deleteResult method of the class. When Spring sees #Transactional it creates a proxy object with transactional behavior. Unless you're using AspectJ it won't change the class itself but create a new one, proxy. So when you autowire this bean you will be able use proxy's method that runs transaction related logic. But in your case you're referencing to the method of the class, not proxy.
The second problem is that Spring (again if AspectJ is not used) can't proxy non-public methods.
Summary: make the deleteResult method public somehow and use proxied one. As a suggestion, use another component with deleteResult there.
You are catching exception out of for loop, while your requirement says you want to continue the loop for other objects in list.
Put your try/catch block with-in loop. It should work fine
public LabResResponse saveLabResult(List<LabResInvstResultDto> invstResults) {
LabResResponse labResResponse = new LabResResponse();
List<Long> relInvstid = new ArrayList<Long>();
try{
if(invstResults != null){
List<LabResInvstResult> labResInvstResults = mapper.mapAsList(invstResults, LabResInvstResult.class);
for(LabResInvstResult dto: labResInvstResults){
if(dto != null){
//delete all child records before save.
try {
deleteResult(dto, relInvstid);
} catch(Exception e){
e.printStackTrace();
}
}
}
}
labResResponse.setRelInvstids(relInvstid);
}catch(Exception e){
e.printStackTrace();
}
return labResResponse;
}

how to write error message to DB with EF when SaveChanges?

With EF, any data value in Entity instance can be saved back to database by calling SaveChanges which can be overridden to add custom action.
So I try to override SaveChanges in following way:
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
try
{
return base.SaveChanges(options);
}
catch (Exception ex)
{
//error log here
//write the error message to database table errorlog
throw ex;
}
}
when SaveChange failed, I want to grab the exception and save the error message to a table in same database. With about code, even save data to table errorlog, also should call SaveChanges. How to resolve this problem?
Initialize a new context instance in your catch block and log the error.
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
try
{
return base.SaveChanges(options);
}
catch (Exception ex)
{
var context = new MyContext();
// your log class instance populated with relevant details
var error = new Error { Message = ex.Message; };
context.Errors.AddObject(error);
context.SaveChanges();
throw;
}
}
In addition to #Eranga's advice use separate context type just for error logging (it will map only Error entity). This new context type will not have overriden SaveChanges - that will avoid infinite loop in case of error fired during error saving.

Google web toolkits

Can anyone please suggest a website where I can find step by step instructions on how to add jdbc to a gwt project and how to access data from a database within a gwt project? I'm new to GWT and can't to find any good resources to learn from.
Thanks
GWT is a client side technology - it creates code that runs on a browser. You can not talk to databases directly from browser. You need an intermediary servlet server. Here is what you need to do:
Use GWT-RPC for your GWT code to talk to the servlet server. There are a lot of good tutorials around the web.
Create server-side code that uses JDBC to talk to your database. Ankit already provided you with a link to example: http://code.google.com/p/gwt-examples/wiki/project_MySQLConn
You can also take a direct route and use one of the pre-packaged frameworks that allow you to talk "directly" from GWT to database, where framework provides the intermediate step (GWT-RPC to JDBC): gwtexpress
Just follow the google's tutorial itself. GWT is a java framework which converts java code into javascript code on compilation. And please dont confuse with database connection and gwt application. They are totally independent. In gwt application you will be seeing client & server packages. Only classes inside client package will be compiled to javascript code. You have to write jdbc code inside the server package. These codes will not be (can't be) compiled into javascript.
To bring the database data into client side you have to make rpc call.
I hope this information helps you for your basic understanding.
In that code you can learn how to connect database in gwt with jdbc
public class ExampleServiceImpl extends RemoteServiceServlet implements ExampleService{
//private Connection con=null;
private String status;
private String url="jdbc:mysql://localhost:3306/test";
private String user="test";
private String pass = "123456";
private Person people;
private ResultSet resultSet=null;
private Statement stm=null;
private Connection con=null;
private Statement stm2=null;
private Connection conn2=null;
private ResultSet resultSet2=null;
private MySqlConnection conn=new MySqlConnection();
#Override
public Person getPerson(String name,String surname,int password) {
Person personinfo=new Person();
personinfo.setName(name);
personinfo.setSurname(surname);
personinfo.setPassword(password);
ResultSet resultSet=null;
Statement stm=null;
Connection con=null;
MySqlConnection conn=new MySqlConnection();
con = conn.getConnection();
try {
stm = ((Connection) con).createStatement();
} catch (SQLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
String sorgu = "SELECT * FROM person";
try {
resultSet = stm.executeQuery(sorgu);
} catch (SQLException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
while(true){
String sql = "INSERT INTO person " +
"VALUES ("+ password +", '" + name+ "','" + surname + "')";
try {
stm.executeUpdate(sql);
} catch (SQLException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
((Connection) con).setAutoCommit(false);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
((Connection) con).commit();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
stm.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return personinfo;
}
}
public class MySqlConnection extends RemoteServiceServlet {
private static final long serialVersionUID = 1L;
public static Connection con;
public static Connection getConnection()
{
try
{
if(con==null)
{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mysqlconn?user=root&password=123456";
con= DriverManager.getConnection(url);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return con;
}
public static void CloseConnection()
{
try
{
con.close();
con = null;
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}