Can someone tell me why my entityTransaction doesn't works?
rollback() has no effect, commit() too, i think also begin(). I tried to disable autocommit:
spring.datasource.auto-commit=false
spring.datasource.hikari.auto-commit=false
but there is no effect after that, still that transactions don't work. Here is my service:
#Service
public class MyService {
...
#Autowired
private final JdbcTemplate jdbcTemplate;
...
#Autowired
private EntityManagerFactory entityManagerFactory;
...
#Transactional
public ArrayList<String> executeSQL(String[] split) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction entityTransaction = entityManager.getTransaction();
ArrayList<String> listException = new ArrayList<String>();
boolean flag = false;
for (int i = 0; i < split.length; ++i) {
String query = split[i];
try {
entityTransaction.begin();
mapList = jdbcTemplate.queryForList(query);
entityTransaction.commit();
listException.add("Success!");
} catch (Exception e1) {
entityTransaction.rollback();
try {
entityTransaction.begin();
int rows = jdbcTemplate.update(query);
entityTransaction.commit();
listException.add("Sucesss! { [" + rows + "] <-- affected rows }");
} catch (Exception e2) {
entityTransaction.rollback();
flag = true;
listException.add(e2.getCause().getMessage());
}
}
}
entityManager.close();
if(flag){
mapList = emptyMapList;
updateFlag = false;
}
else{
updateFlag = true;
}
return listException;
}
...
Related
I have an old java code and I'm quite new to java spring, I need to read json files and merge data from entity to Oracle database.
I test my code without the entityManager.merge() and it works well.
But now, I tried with merge and got an EJBException
javax.ejb.EJBException: EJB Exception: : javax.persistence.TransactionRequiredException: The method public abstract java.lang.Object javax.persistence.EntityManager.merge(java.lang.Object) must be called in the context of a transaction.
at weblogic.persistence.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:148)
at weblogic.persistence.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:103)
at weblogic.persistence.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:138)
at weblogic.persistence.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:91)
at com.sun.proxy.$Proxy592.merge(Unknown Source)
at be.smals.ideploy.manager.ReleaseManager.updateReleases(ReleaseManager.java:69)
at be.smals.ideploy.manager.ReleaseManager.getActiveReleaseList(ReleaseManager.java:144)
This is my code :
#Stateless
#Local
#TransactionAttribute(TransactionAttributeType.SUPPORTS)
public class ReleaseManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ReleaseManager.class);
private static final String STATUS_CLOSED = "inactive";
private static final String STATUS_OPEN = "active";
private Integer cpt_active = 0;
private Integer cpt_inactive = 0;
#PersistenceContext(unitName = "deployment")
private EntityManager em;
public void updateReleases() {
try {
for (GetReleaseList releaseList : getRelease(STATUS_OPEN)) {
Service service_active = new Service();
Release release_active = new Release();
List<ResponseJson> response = getResponse(STATUS_OPEN);
service_active.setId(response.get(cpt_active).getResult().getService_id());
release_active.setService(service_active);
String releaseId = releaseList.getNumber();
String releaseId_format = releaseId.replace("CHG","");
release_active.setId(releaseId_format);
release_active.setName(releaseList.getShortDescription());
release_active.setActive(Boolean.TRUE);
LOGGER.info("RELEASE NUMBER FORMATED : " + releaseId_format);
em.merge(release_active);
cpt_active += 1;
}
for (GetReleaseList releaseList : getRelease(STATUS_CLOSED)) {
Service service_inactive = new Service();
Release release_inactive = new Release();
List<ResponseJson> response = getResponse(STATUS_CLOSED);
service_inactive.setId(response.get(cpt_inactive).getResult().getService_id());
release_inactive.setService(service_inactive);
String releaseId = releaseList.getNumber();
String releaseId_format = releaseId.replace("CHG","");
release_inactive.setId(releaseId_format);
release_inactive.setName(releaseList.getShortDescription());
release_inactive.setActive(Boolean.FALSE);
LOGGER.info("RELEASE NUMBER FORMATED : " + releaseId_format);
em.merge(release_inactive);
cpt_inactive += 1;
}
}catch (TransactionException ex) {
throw new TechnicalException(ex);
}
Query q = em.createQuery("update Deployment d set d.release = null where d.status.id = :status and d.release.id in ( select r.id from Release r where r.active = :active) ");
LOGGER.info("Create Query : " + q);
q.setParameter("status", State.CREATING);
q.setParameter("active", Boolean.FALSE);
int updated = q.executeUpdate();
LOGGER.info("Updated release.id of " + updated + " deployments");
}
// getRelease element for Release entity except service ID
private List<GetReleaseList> getRelease(String STATUS) {
Gson gson = new Gson();
BufferedReader buffer_reader = null;
LOGGER.info(STATUS);
try {
buffer_reader = new BufferedReader(new FileReader("/tmp/snow/Release_manager_"+STATUS+".json"));
File File_snow = new File("/tmp/snow/Release_manager_"+STATUS+".json");
boolean exists = File_snow.exists();
LOGGER.info(String.valueOf(exists));
}catch (FileNotFoundException ex){
ex.printStackTrace();
}
RESTResponseJson response = gson.fromJson(buffer_reader, RESTResponseJson.class);
return response.getResult();
}
// getServiceID element for Release entity attribute Long service_id
private static List<ResponseJson> getResponse(String STATUS){
Gson gson_service = new Gson();
BufferedReader buffer_reader_service = null;
try {
buffer_reader_service = new BufferedReader(new FileReader("/tmp/snow/Service_id_"+STATUS+".json"));
}catch (FileNotFoundException ex){
ex.printStackTrace();
}
Response response_service = gson_service.fromJson(buffer_reader_service, Response.class);
return response_service.getResponse();
}
public List<Service> getServiceList(){
TypedQuery<Service> q = em.createQuery("SELECT s from Service", Service.class);
List<Service> services = q.getResultList();
return services;
}
public List<ReleaseTO> getInActiveReleaseList() {
TypedQuery<ReleaseTO> query = em.createQuery("select new be.smals.ideploy.to.ReleaseTO(r.id, r.name) from Release r where r.active=:active ORDER BY UPPER(r.name)", ReleaseTO.class);
query.setParameter("active", Boolean.FALSE);
List<ReleaseTO> result = query.getResultList();
return result;
}
public List<ReleaseTO> getActiveReleaseList() {
updateReleases();
TypedQuery<ReleaseTO> query = em.createQuery("select new be.smals.ideploy.to.ReleaseTO(r.id, r.name) from Release r where r.active=:active ORDER BY UPPER(r.name)", ReleaseTO.class);
query.setParameter("active", Boolean.TRUE);
List<ReleaseTO> result = query.getResultList();
return result;
}
public List<ReleaseTO> getReleaseList() {
TypedQuery<ReleaseTO> query = em.createQuery("select new be.smals.ideploy.to.ReleaseTO(r.id, r.name) from Release r ORDER BY UPPER(r.name)", ReleaseTO.class);
List<ReleaseTO> result = query.getResultList();
return result;
}
}
As suggest the error, is the #TransactionAttribute that don't correspond to my context, if somebody can explain the differencies for TransactionAttributeType.
I also read that it could come from #Stateless statement.
From https://docs.oracle.com/javaee/6/api/javax/ejb/TransactionAttributeType.html
SUPPORTS: If the client calls with a transaction context, the container performs the same steps as described in the REQUIRED case.
REQUIRED: If a client invokes the enterprise bean's method while the client is associated with a transaction context, the container invokes the enterprise bean's method in the client's transaction context.
I think you want "REQUIRED"
ninja is an awesome framework but coming from a spring background, I need to use spring data jpa with ninja.
I want to Autowire a JpaRepository and use it in ninja. Although ninja uses Guice Inject. I keep getting a No implementations found for my class.
the repository:
public interface PortalUserRepository extends JpaRepository<PortalUser, Long> {
PortalUser getPortalUserByUsername(String username);
PortalUser getPortalUserByEmail(String email);
}
the injection
public class SetupDaoV2 {
#Inject
PortalUserRepository portalUserRepository;
public void setup() {
try {
List<PortalUser> portalUsers = portalUserRepository.findAll();
if (portalUsers.size() == 0) {
// Create a new user and save it
PortalUser portalUser = new PortalUser("lsadjfl", "lsdlfs", "kkk lll",
"llskfls#gmail.com", "lsdlfss#",
"lsdfls#gmail.com",
new Timestamp(System.currentTimeMillis()), Boolean.TRUE,
Boolean.TRUE, GenericStatusConstant.ACTIVE, Boolean.TRUE
);
portalUserRepository.save(portalUser);
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
the error
com.google.inject.CreationException: Unable to create injector, see
the following errors:
1) No implementation for com.bw.dd.dsl.repository.PortalUserRepository was bound.
Well, I finally had to implement the whole thing. A shame I couldn't port the wonderful features from spring data jpa into ninja. I coulda used spring, but for office policy on the project.
If someone finds a way, pls holla.
public abstract class JpaRepository<E, K> {
public abstract void create(E entity);
public abstract void edit(E entity) throws Exception;
public abstract void remove(K key) throws IllegalOrphanException, NonexistentEntityException;
public abstract List<E> findAll();
public abstract E findOne(K key);
public abstract int count();
}
public class PortalUserRepository extends JpaRepository<PortalUser, Long> {
private EntityManagerFactory emf = null;
public PortalUserRepository() {
}
public PortalUserRepository(EntityManagerFactory emf) {
this.emf = emf;
}
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void create(PortalUser entity) {
if (entity.getUserTokens() == null) {
entity.setUserTokens(new ArrayList<UserToken>());
}
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
Collection<UserToken> attachedUserTokens = new ArrayList<UserToken>();
for (UserToken userTokensUserTokenToAttach : entity.getUserTokens()) {
userTokensUserTokenToAttach = em.getReference(userTokensUserTokenToAttach.getClass(), userTokensUserTokenToAttach.getId());
attachedUserTokens.add(userTokensUserTokenToAttach);
}
entity.setUserTokens(attachedUserTokens);
em.persist(entity);
for (UserToken userTokensUserToken : entity.getUserTokens()) {
PortalUser oldPortalUserOfUserTokensUserToken = userTokensUserToken.getPortalUser();
userTokensUserToken.setPortalUser(entity);
userTokensUserToken = em.merge(userTokensUserToken);
if (oldPortalUserOfUserTokensUserToken != null) {
oldPortalUserOfUserTokensUserToken.getUserTokens().remove(userTokensUserToken);
oldPortalUserOfUserTokensUserToken = em.merge(oldPortalUserOfUserTokensUserToken);
}
}
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
public void edit(PortalUser entity) throws Exception {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
PortalUser persistentPortalUser = em.find(PortalUser.class, entity.getId());
Collection<UserToken> userTokensOld = persistentPortalUser.getUserTokens();
Collection<UserToken> userTokensNew = entity.getUserTokens();
List<String> illegalOrphanMessages = null;
for (UserToken userTokensOldUserToken : userTokensOld) {
if (!userTokensNew.contains(userTokensOldUserToken)) {
if (illegalOrphanMessages == null) {
illegalOrphanMessages = new ArrayList<String>();
}
illegalOrphanMessages.add("You must retain UserToken " + userTokensOldUserToken + " since its entity field is not nullable.");
}
}
if (illegalOrphanMessages != null) {
throw new IllegalOrphanException(illegalOrphanMessages);
}
Collection<UserToken> attachedUserTokensNew = new ArrayList<UserToken>();
for (UserToken userTokensNewUserTokenToAttach : userTokensNew) {
userTokensNewUserTokenToAttach = em.getReference(userTokensNewUserTokenToAttach.getClass(), userTokensNewUserTokenToAttach.getId());
attachedUserTokensNew.add(userTokensNewUserTokenToAttach);
}
userTokensNew = attachedUserTokensNew;
entity.setUserTokens(userTokensNew);
entity = em.merge(entity);
for (UserToken userTokensNewUserToken : userTokensNew) {
if (!userTokensOld.contains(userTokensNewUserToken)) {
PortalUser oldPortalUserOfUserTokensNewUserToken = userTokensNewUserToken.getPortalUser();
userTokensNewUserToken.setPortalUser(entity);
userTokensNewUserToken = em.merge(userTokensNewUserToken);
if (oldPortalUserOfUserTokensNewUserToken != null && !oldPortalUserOfUserTokensNewUserToken.equals(entity)) {
oldPortalUserOfUserTokensNewUserToken.getUserTokens().remove(userTokensNewUserToken);
oldPortalUserOfUserTokensNewUserToken = em.merge(oldPortalUserOfUserTokensNewUserToken);
}
}
}
em.getTransaction().commit();
} catch (Exception ex) {
String msg = ex.getLocalizedMessage();
if (msg == null || msg.length() == 0) {
Long id = entity.getId();
if (findOne(id) == null) {
throw new NonexistentEntityException("The entity with id " + id + " no longer exists.");
}
}
throw ex;
} finally {
if (em != null) {
em.close();
}
}
}
public void remove(Long key) throws IllegalOrphanException, NonexistentEntityException {
EntityManager em = null;
try {
em = getEntityManager();
em.getTransaction().begin();
PortalUser portalUser;
try {
portalUser = em.getReference(PortalUser.class, key);
portalUser.getId();
} catch (EntityNotFoundException enfe) {
throw new NonexistentEntityException("The portalUser with id " + key + " no longer exists.", enfe);
}
List<String> illegalOrphanMessages = null;
Collection<UserToken> userTokensOrphanCheck = portalUser.getUserTokens();
for (UserToken userTokensOrphanCheckUserToken : userTokensOrphanCheck) {
if (illegalOrphanMessages == null) {
illegalOrphanMessages = new ArrayList<String>();
}
illegalOrphanMessages.add("This PortalUser (" + portalUser + ") cannot be destroyed since the UserToken " + userTokensOrphanCheckUserToken + " in its userTokens field has a non-nullable portalUser field.");
}
if (illegalOrphanMessages != null) {
throw new IllegalOrphanException(illegalOrphanMessages);
}
em.remove(portalUser);
em.getTransaction().commit();
} finally {
if (em != null) {
em.close();
}
}
}
public List<PortalUser> findAll() {
EntityManager em = getEntityManager();
try {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(PortalUser.class));
Query q = em.createQuery(cq);
return q.getResultList();
} finally {
em.close();
}
}
public PortalUser findOne(Long key) {
EntityManager em = getEntityManager();
try {
return em.find(PortalUser.class, key);
} finally {
em.close();
}
}
public int count() {
EntityManager em = getEntityManager();
try {
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
Root<PortalUser> rt = cq.from(PortalUser.class);
cq.select(em.getCriteriaBuilder().count(rt));
Query q = em.createQuery(cq);
return ((Long) q.getSingleResult()).intValue();
} finally {
em.close();
}
}
public PortalUser findPortalUserByUsername(String username){
EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select s from PortalUser s where s.username = '" + username + "'");
return (PortalUser)q.getSingleResult();
} finally {
em.close();
}
}
You need to mark PortalUserRepository class with #Repository as shown below:
#Repository
public interface PortalUserRepository extends JpaRepository<PortalUser, Long> {
//your methods
}
Also, ensure that you have got #EnableJPARepositories so that Spring container can scan for your repository interfaces and provide the implementations for them and then inject them into your SetupDaoV2 bean.
I have to write some dao tests for project where I want to:
create DDL schema from database (MySQL);
create tables in another test database in memory (H2);
insеrt some data to database;
select the just inserted item;
check some data from this item.
This is my test:
public class BridgeDBTest {
private static String JDBC_DRIVER;
private static String JDBC_URL;
private static String USER;
private static String PSWD;
private static final Logger logger = LoggerFactory.getLogger(BridgeDBTest.class);
#BeforeGroups(groups = "bridgeDB")
public void init(){
try {
JDBC_DRIVER = org.h2.Driver.class.getName();
JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
USER = "root";
PSWD = "";
new HibernateTestUtil().setDialect("org.hibernate.dialect.HSQLDialect")
.translateCreateDllToOutputStream(new FileOutputStream(new File("src/test/resources/createSchema.sql")));
RunScript.execute(JDBC_URL, USER, PSWD, "src/test/resources/createSchema.sql", Charset.forName("UTF8"), false);
insertDataset(readDataSet());
}
catch (Exception expt) {
expt.printStackTrace();
logger.error("!!!" + expt);
throw new RuntimeException(expt.getMessage());
}
}
#Test(groups = "bridgeDB")
public void getItem(){
BridgeDAOImpl dao = new BridgeDAOImpl();
dao.setSessionFactory(new HibernateTestUtil().getSessionFactory());
try {
Bridge bridge = dao.get(1L);
assert(bridge.getName().equals("TEST-CN-DEVBOX01"));
} catch (ServiceException e) {
e.printStackTrace();
}
}
#AfterGroups(groups = "bridgeDB")
public void dropTables(){
try {
new HibernateTestUtil().setDialect("org.hibernate.dialect.HSQLDialect")
.translateDropDllToOutputStream(new FileOutputStream(new File("src/test/resources/dropSchema.sql")));
}
catch (Exception expt) {
expt.printStackTrace();
logger.error("!!!" + expt);
throw new RuntimeException(expt.getMessage());
}
}
private IDataSet readDataSet() throws Exception{
return new FlatXmlDataSetBuilder().build(new File("src/test/resources/datasetForTest.xml"));
}
private void insertDataset(IDataSet dataSet) throws Exception{
IDatabaseTester databaseTester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PSWD);
databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
databaseTester.setDataSet(dataSet);
databaseTester.onSetup();
}
}
BridgeDAOImplused class HibernateUtilfrom src/main/..., but I need to use my class HibernateTestUtil from src/test/.... It's modified HibernateUtil fitted for my test (there I set parameters for Configuration class).
BridgeDAOImpl (See 5 line in try block):
public class BridgeDAOImpl extends GenericDAOImpl<Bridge, Long> implements BridgeDAO {
//...
public SearchResult<Bridge> list(int from, int limit, String filter, String order, Long authId) throws ServiceException {
SearchResult<Bridge> results = null;
Search search = new Search(Bridge.class);
Session session = getSessionFactory().getCurrentSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
search.setFirstResult(from);
search.setMaxResults(limit);
HibernateUtil.buildSearch(filter, order, search, aliases);
results = searchAndCount(search);
transaction.commit();
}
catch (Exception expt) {
logger.error("!!!", expt);
if (transaction != null) {
transaction.rollback();
}
throw new ServiceException(expt.getMessage());
}
finally {
// session.close();
}
return results;
}
//...
}
How I can test my dao without modifying it?
I want to rollback a transaction in function say xyz()
This xyz calls another function say abc() within it that has its own transaction tx. If due to an exception Abc() rolls back its transaction,hence transaction in xyz() should also get rolled back.
How can i rollback transaction in xyz() ?
This is my code.
public String execute() throws Exception {
// viewReadOnly();
Session sf=null;
Transaction tx=null;
try {
sf = HibernateUtil.getSessionFactory().getCurrentSession();
tx = sf.getTransaction();
tx.begin();
//sosFile.setCmaId(1);
//sosFile.setSosFileId(1);
//sosFile.setHeadImage(new ImageService().readImageOldWay(headFile));
//sosFile.setFootImage(new ImageService().readImageOldWay(footFile));
//if(new ImageService().readImageOldWay(headFile) != null)
System.out.println("FLAG="+flag);
if(headFile!=null)
{
for (int i = 0; i < headFile.length; i++) {
if (headFile != null) {
sosOrder = new SOSCustomerOrderFile();
sosOrder.setCmaId(cmaId);
sosOrder.setFileData(new ImageService().readImageOldWay(headFile[i]));
sosOrder.setFileName(new File(sosorderfilename[i]).getName());
sosOrder.setSosStage(flag);
sf.saveOrUpdate(sosOrder);
}
}
}
if(footFile!=null)
{
for (int i = 0; i < footFile.length; i++) {
if (footFile != null) {
sosCheque.setCmaId(cmaId);
sosCheque.setFileData(new ImageService().readImageOldWay(footFile[i]));
sosCheque.setFileName(new File(soschequefilename[i]).getName());
sosCheque.setSosStage(flag);
sf.saveOrUpdate(sosCheque);
}
}
}
// tx.begin();
// sf.close();
/*Session sf1 = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx1 = sf1.getTransaction();
tx1.begin();*/
if (cheque_no_hidden != null || cheque_amount_hidden != null || cheque_bank_hidden != null || cheque_date_hidden != null) {
for (int i = 0; i < chequeCounter; i++) {
cheque_no = cheque_no_hidden.split(",");
cheque_amount = cheque_amount_hidden.split(",");
cheque_bank = cheque_bank_hidden.split(",");
cheque_date = cheque_date_hidden.split(",");
SOSChequeDetails sosChequeD = new SOSChequeDetails();
sosChequeD.setChequeNo(cheque_no[i]);
sosChequeD.setChequeAmount(cheque_amount[i]);
sosChequeD.setChequeBank(cheque_bank[i]);
sosChequeD.setChequeDate(cheque_date[i]);
sosChequeD.setCmaId(cmaId);
sosChequeD.setSosStage(flag);
sf.saveOrUpdate(sosChequeD);
// tx1.begin();
// sf1.close();
}
}
if(saveSOSValue.saveSOS(sosValues, cmaId,flag,sf,tx))
{
sosValues.setFlag(1);
}
else
{
sosValues.setFlag(2);
}
if(flag.equalsIgnoreCase("sosSUBMIT"))
{
CmaDetails cmaD = (CmaDetails) sf.get(CmaDetails.class, cmaId);
/* for(int j=0;j<5;j++){
LeaveManagementManager manager=new LeaveManagementManager();
Userinfo userinfoLeave=manager.getUserInfoObjforsos(sosWorkflow_status);
workflow.setFromDesignation(userinfoLeave.getWorkflowdesignation().getWorkflowDesignationId());
List<Workflow> workflowListTemp=new ArrayList<Workflow>();
workflowListTemp=(new WorkflowService().performAction(workflow));
if(userinfoLeave.getOutOfOffice()!=null && userinfoLeave.getOutOfOffice().equals("OOO")){
date.setSeconds(date.getSeconds()+1);
wfs=makeEntryInWorkflow(sdm,formater,now, date, workflowListTemp, cmaDetails, query, i, ToEmailIdTemp, ToEmailId,wfs,null);
}else{
j=5;
}
}*/
boolean decideRollback=approveSOSvalue.ApprovalSOSWorkflow(sosWorkflow_status,sosValues,cmaD,"create",1,"flag");
if(decideRollback==false){
tx.rollback();
}
}
} catch (Exception e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}
viewDocuments();
viewCheques();
/* ComplianceCMA complianceCMA = new ComplianceCMA();
cmaDetails = complianceCMA.getCma(cmaId);
cmaDetails.setStage(Constants.STAGE_SOS_UPLOAD);
UpdateCMA updateStage = new UpdateCMA();
updateStage.performAction(cmaDetails);*/
ViewSOSDetails viewsos=new ViewSOSDetails();
viewsos.home();
return SUCCESS;
}
This function calls
public boolean ApprovalSOSWorkflow(SOSWorkflow_status sosWorkflowstatuscomment,SOSValues sosValues,CmaDetails cmaId,String Action,int bpaID,String flag)
function.
Please help.
Best way to solve this is to not use a new transaction in abc(). Start the transaction in xyz and use transaction prorogation required in abc(). That way Tx in abc() will lap onti the the Tx which xyz() started and if abc throws an exception catch it and rollback the Tx so that the Tx in Xyz also rolls back. Are you using Spring? If not then you should Spring makes solving such cases very easy using annotations.
You could have transaction Abc() return a boolean stating whether it had to roll itself back, and then use that boolean in xyz() to determine whether to roll itsel back.
I've got a custom exception called "LoginException". It might be thrown from any class. So I want to make an advice to do something(for example, print "Ooops") after throwing. So I decided to use AOP. Something like this:
#Aspect
public class LogoutAdvice {
#AfterThrowing(throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, LoginException e) {
System.out.println("IDS HABBENING");
}
}
Code:
#Transactional
public DynamicTable getTable(int status_id, HttpServletRequest request)
throws HibernateException, LoginException, SQLException {
try {
ResultSet rs = requestDAO.getRequestResultSet(
cookieDAO.get(SESS_ATTR, request), status_id);
DynamicTable dt = new DynamicTable();
String[] columnArray;
LinkedList<String[]> dataList = new LinkedList<String[]>();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
columnArray = new String[columnCount - META_COLUMNS_COUNT];
for (int i = 0; i < columnArray.length; i++) {
columnArray[i] = rsmd.getColumnName(META_COLUMNS_COUNT + i + 1);
}
dt.setTitleArray(columnArray);
while (rs.next()) {
String[] dataArray = new String[columnArray.length];
for (int i = 0; i < columnArray.length; i++) {
dataArray[i] = ParamUtil.toString(rs
.getObject(META_COLUMNS_COUNT + i + 1));
}
dataList.add(dataArray);
}
dt.setDataList(dataList);
return dt;
} catch (SQLException e) {
String message = e.getMessage();
String[] errorsArray = AuthErrorsConst.ERROR;
for (int i = 0; i < errorsArray.length; i++) {
if (message.contains(errorsArray[i])) {
throw new LoginException(); // LOOK AT THIS
}
}
throw e;
}
}
How can I do that?
Be sure the exception is being thrown
catch (SQLException e) {
String message = e.getMessage();
String[] errorsArray = AuthErrorsConst.ERROR;
for (int i = 0; i < errorsArray.length; i++) {
if (message.contains(errorsArray[i])) {
System.out.println("throwing LoginException")// NEW
throw new LoginException(); // LOOK AT THIS
}
}
throw e;
}
About
#Aspect
public class LogoutAdvice {
#AfterThrowing(throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, LoginException e) {
System.out.println("IDS HABBENING");
}
}
Be sure Spring has enable to work with #Aspect and furthermore it be able to scan your LogoutAdvice aspect, normally I declare them how
#Aspect
#Component// to be scanned by Spring
public class LogoutAdvice {
Change your #AfterThrowing to
#AfterThrowing(pointcut = "execution(* *.*(..))",throwing = "e")
Use a point cut in your #AfterThrowing annotation
Therefore your annotation will need to look something like below
#AfterThrowing(pointcut = "execution(public * *(..))",throwing = "e")
Please refer to below link for elaborate explanation:
http://www.compiletimeerror.com/2013/05/spring-aop-after-throwing-advice.html#.VCAnsvmSw2c
1) Check you LoginException class as it should be a proper exception class.
2) throw the exception object "e" in catch block
3)
#Aspect
#Component
public class LogoutAdvice {
#AfterThrowing(pointcut = "execution (* * com..*(..)", throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, LoginException e) {
System.out.println("IDS HABBENING");
}
}
4) in spring configuration file
<aop:aspectj-autoproxy/>
thats enough.