/*
Copyright 2015 Ant Kutschera
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ch.maxant.jca_demo.client;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.sql.DataSource;
import ch.maxant.generic_jca_adapter.ExecuteCallback;
import ch.maxant.generic_jca_adapter.TransactionAssistanceFactory;
import ch.maxant.generic_jca_adapter.TransactionAssistant;
import ch.maxant.jca_demo.acquirer.Acquirer;
import ch.maxant.jca_demo.acquirer.AcquirerWebServiceService;
import ch.maxant.jca_demo.bookingsystem.BookingSystem;
import ch.maxant.jca_demo.bookingsystem.BookingSystemWebServiceService;
import ch.maxant.jca_demo.letterwriter.LetterWebServiceService;
import ch.maxant.jca_demo.letterwriter.LetterWriter;
/** A Java 6 compatible implementation */
@Stateless
public class SomeServiceThatBindsResourcesIntoTransaction_JavaSE6 {
private final Logger log = Logger.getLogger(this.getClass().getName());
@Resource(lookup = "java:/maxant/Acquirer")
private TransactionAssistanceFactory acquirerFactory;
@Resource(lookup = "java:/maxant/BookingSystem")
private TransactionAssistanceFactory bookingFactory;
@Resource(lookup = "java:/maxant/LetterWriter")
private TransactionAssistanceFactory letterWriterFactory;
@Resource(lookup = "java:/jdbc/MyXaDS")
private DataSource ds;
@Resource
private SessionContext ctx;
public String doSomethingInvolvingSeveralResources(String refNumber)
throws Exception {
Acquirer acquirer = new AcquirerWebServiceService().getAcquirerPort();
BookingSystem bookingSystem = new BookingSystemWebServiceService().getBookingSystemPort();
LetterWriter letterWriter = new LetterWebServiceService().getLetterWriterPort();
TransactionAssistant acquirerTransactionAssistant = null;
TransactionAssistant bookingTransactionAssistant = null;
TransactionAssistant letterWriterTransactionAssistant = null;
try {
acquirerTransactionAssistant = acquirerFactory.getTransactionAssistant();
bookingTransactionAssistant = bookingFactory.getTransactionAssistant();
letterWriterTransactionAssistant = letterWriterFactory.getTransactionAssistant();
int id = insertFirstRecordIntoDatabase();
String acquirerResponse = acquirerTransactionAssistant
.executeInActiveTransaction(new ExecuteCallback<String>(){
@Override
public String execute(String txid) throws Exception {
return acquirer.reserveMoney(txid, refNumber);
}
});
log.log(Level.INFO, "reserved money...");
String bookingResponse = bookingTransactionAssistant.executeInActiveTransaction(new ExecuteCallback<String>() {
@Override
public String execute(String txid) throws Exception {
return bookingSystem.reserveTickets(txid, refNumber);
}
});
String letterResponse = letterWriterTransactionAssistant.executeInActiveTransaction(new ExecuteCallback<String>() {
@Override
public String execute(String txid) throws Exception {
return letterWriter.writeLetter(txid, refNumber);
}
});
insertAnotherRecordIntoDatabase(refNumber, id);
String response = acquirerResponse + "/" + bookingResponse + "/" + letterResponse;
log.log(Level.INFO, "returning " + response);
return response;
} catch (SQLException e) {
// have to catch SQLException explicitly since
// its considered to be an application exception
// since it inherits from Exception and not
// RuntimeException - kinda sucks really.
ctx.setRollbackOnly();
throw e;
} finally {
if(acquirerTransactionAssistant != null){
acquirerTransactionAssistant.close();
}
if(bookingTransactionAssistant != null){
bookingTransactionAssistant.close();
}
if(letterWriterTransactionAssistant != null){
letterWriterTransactionAssistant.close();
}
}
}
private void insertAnotherRecordIntoDatabase(String refNum, int id) throws SQLException {
try (Connection database = ds.getConnection();
PreparedStatement statement = database.prepareStatement("insert into temp.address values (null,?,?)")) {
statement.setString(2, "THIRD_" + new SimpleDateFormat("yyyy/MM/dd_HH:mm:ss.SSS").format(new Date()));
if ("FAILDB".equals(refNum)) {
statement.setInt(1, 0); // fails with FK Constraint exception
} else {
statement.setInt(1, id);
}
int cnt = statement.executeUpdate();
log.log(Level.INFO, "wrote to db... " + cnt);
}
}
private int insertFirstRecordIntoDatabase() throws SQLException {
int id;
try (Connection database = ds.getConnection();
PreparedStatement statement = database.prepareStatement(
"insert into temp.person values (null,?)",
Statement.RETURN_GENERATED_KEYS)) {
statement.setString(1, "FIRST_" + new SimpleDateFormat("yyyy/MM/dd_HH:mm:ss.SSS").format(new Date()));
int cnt = statement.executeUpdate();
ResultSet generatedKeys = statement.getGeneratedKeys();
generatedKeys.next();
id = generatedKeys.getInt(1);
log.log(Level.INFO, "wrote to db... " + cnt + " with ID " + id);
}
return id;
}
}