How to save chat history into database? - java

I am writing a chat application using java websocket, now I need to save chat history, so when calling onMessage method I create my object, set its property and save it to data base,but with no reason It doesn't recieve to persist part, here is my code:
#OnMessage
public void onMessage(final Session session,
final ChatMessageBean chatMessage) {
String sender = (String) session.getUserProperties().get("user");
try {
for (Session s : session.getOpenSessions()) {
if (s.isOpen()
&& ((chatMessage.getReceiver()).equals(s
.getUserProperties().get("user")) || sender
.equals(s.getUserProperties().get("user")))) {
s.getBasicRemote().sendObject(chatMessage);
System.err.println("chatMessage is : " + chatMessage);
System.err.println("user is : "
+ s.getUserProperties().get("user"));
}
}
} catch (IOException | EncodeException e) {
log.log(Level.WARNING, "onMessage failed", e);
}
ChatMessage chatConv = new ChatMessage();
chatConv.setMessage("hihii");
chatConv.setRecievedDate(new Date());
chatConv.setSeenStaus(true);
chatConv.setSenderId("7923");
chatConv.setReciever("702");
chatCrud.addChat(chatConv);
}
and my addChat method on chatCrud Class:
public class ChatCrud {
#Inject
EntityManager em;
public String addChat(ChatMessage chat) {
try{
em.getTransaction().begin();
em.persist(chat);
em.getTransaction().commit();
}catch(Exception e){
System.out.println("!!!!!! "+e);
}
return "OK";
}
}
I changed my method to catch exception, The sysout result was:
!!!!!! org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped
Is onMessage method the wrong place to save history of chat?

Related

Unit Testing a Kafka SpringBoot producer

I am trying to create a unit test for my Kafka Producer which is integrated into a file. Here's my Kafka Producer:
FileName: MessageProducer.java
public boolean sendMessage(ReceivedMessage message) {
private String topicName = "output-flow";
try{
logger.info("Sending message: {} to topic: {}", message, topicName);
kafkaProducer.send(topicName, message).get();
return true;
} catch (Exception e){
logger.error("Error sending message: {} to topic: {}", message, topicName, e);
return false;
}
}
And here is what I have done so far for my unit test, obviously, with not success at all:
#Mock
private KafkaTemplate<String, ReceivedMessage > kafkaProducer;
private static final String TRANSACTION_TOPIC = "test";
// Function for parameterized values
#ParameterizedTest
#MethodSource("getTransactionProvider")
public void sendMessageTest(ReceivedMessage message) {
MessageProducer mockProducer = new MessageProducer(kafkaProducer);
when(kafkaProducer.send(TRANSACTION_TOPIC, message)).thenReturn({no idea what to put here});
when(mockProducer.sendMessage(message)).thenReturn(true);
assertTrue(mockProducer.sendMessage(message));
}
// Test for exception
// Fails too
#ParameterizedTest
#MethodSource("getTransactionProvider")
public void sendMessageTest_ThrowsException(ReceivedMessage message) {
MessageProducer mockProducer = new MessageProducer(kafkaProducer);
when(kafkaProducer.send(TRANSACTION_TOPIC, message)).thenThrow(new RuntimeException());
assertThrows(RuntimeException.class, () -> mockProducer.sendMessage(null));
}
I get Exception: org.opentest4j.AssertionFailedError: Expected java.lang.RuntimeException to be thrown, but nothing was thrown. for the latter unit test.
If I understood your question, you should return a new SendResult that would have the methods implemented with the data you expect
https://docs.spring.io/spring-kafka/api/org/springframework/kafka/support/SendResult.html
And wrap it in a Future
ListenableFuture<SendResult<K,​V>>
Alternatively, make sendMessage void method (or return a Future itself), and pass in a producer callback parameter that's carried through to send, rather than making it block. Then you can assert the response of the callback
Welcome to SO...
Why does your test case fail?
Because your logic will not throw an error.
Your function will not throw an exception since you catch the exception inside the function as follow and you return boolean value.
catch (Exception e){
logger.error("Error sending message: {} to topic: {}", message, topicName, e);
return false;
}
In that case, you need to test whether the function returns false or not.
As I commented earlier, don't block the main thread by calling the get method in the future object. You can simply implement the future callbacks which can be invoked once you get the result as following
public void sendMessage(ReceivedMessage message) {
private String topicName = "output-flow";
try{
logger.info("Sending message: {} to topic: {}", message, topicName);
ListenableFuture<SendResult<String, String>> future = kafkaProducer.send(topicName, message);
future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
#Override
public void onSuccess(SendResult<String, String> result) {
System.out.println("Message Sent " + result.getRecordMetadata().timestamp());
//your logic for the success scenario
}
#Override
public void onFailure(Throwable ex) {
System.out.println(" sending failed ");
// your logic if failed
throw new RuntimeException("Kafka Failed");
}
});
} catch (Exception e){
logger.error("Error sending message: {} to topic: {}", message, topicName, e);
throw new RuntimeException("Exception occurred");
}
}

Error while Creating JMS Message Producer in jboss EAP 7

I have configured JMS topic in JBOSS_EAP_7.0 and write a simple java code to create a message producer. I have the following stateless bean
#Stateless
public class ExchangeSenderFacadeWrapperBean {
private static final OMSLogHandlerI logger = new Log4j2Handler("ClientSenderFacadeBean");
#Resource(lookup = "java:/JmsXA") // inject ConnectionFactory (more)
protected ConnectionFactory factory;
#Resource(lookup = "java:/jms/topic/ORD_CLINT_PUSH")
protected Topic target;
private Connection connection = null;
private Session session = null;
public void sendMessage(String message) {
MessageProducer producer= null;
try {
if(connection==null){ //todo verify
connection = factory.createConnection();
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(target);
producer.setDisableMessageID(true);
TextMessage outmsg = session.createTextMessage(message);
producer.send(outmsg);
logger.info("Message was sent to Topic");
producer.setTimeToLive(900000);//15min //todo
} catch (Exception e) {
logger.error(" Error when sending order to jboss:", e);
throw new OMSCoreRuntimeException(e.getMessage(), e);
} finally {
try {
if (producer != null)
producer.close();
} catch (JMSException e) {
logger.warn("\n jms producer close error:",e);
}
try {
if (session != null)
session.close();
} catch (JMSException e) {
logger.warn("\n jms session close error:",e);
}
}
}
This works fine until i made simple change to move sendMessage(String message) method to pojo class as follow.
#Stateless(name = "ExchangeSenderFacadeBean")
#Local({ExchangeSenderFacadeLocalI.class})
public class ExchangeSenderFacadeWrapperBean implements ExchangeSenderFacadeLocalI {
#Resource(lookup = "java:/JmsXA") // inject ConnectionFactory (more)
protected ConnectionFactory factory;
#EJB(beanName = "BeanRegistryLoader")
protected BeanRegistryLoader omsRegistryBean;
protected BeanRegistryCore beanRegistryCore;
#Resource(lookup = "java:/jms/queue/ToExchange")
protected Queue target;
private ExchangeSenderFacadeCoreI exchangeSenderFacadeCore;
#Override
public void sendToExchange(ExchangeMessage exchangeMessage) {
exchangeSenderFacadeCore.sendToExchange(exchangeMessage);
}
#PostConstruct
public void init() {
beanRegistryCore = omsRegistryBean.registry();
if (exchangeSenderFacadeCore == null) {
exchangeSenderFacadeCore = ((BeanRegistryCore) omsRegistryBean.registry()).getExchangeSenderFacadeCoreI();
exchangeSenderFacadeCore.setBeanRegistryCore(omsRegistryBean.registry());
exchangeSenderFacadeCore.setFactory(factory);
exchangeSenderFacadeCore.setTargetQueue(target);
}
}
}
ConnectionFactory and target Queue variables set inside EJB PostConstruct method and pojo class looks like follow, which now contains logic to create and publish method to EJB queue
public class ExchangeSenderFacadeCore implements ExchangeSenderFacadeCoreI {
private static final OMSLogHandlerI logger = new Log4j2HndlAdaptor("ExchangeSenderFacadeCore");
private BeanRegistryCore beanRegistryCore;
private ConnectionFactory factory;
private Connection connection = null;
private Session session = null;
private long ttl = 900000;
protected Queue targetQueue;
public ExchangeSenderFacadeCore() {
if (System.getProperty(OMSConst.SYS_PROPERTY_JMS_TTL) != null && System.getProperty(OMSConst.SYS_PROPERTY_JMS_TTL).length() > 0) {
ttl = Long.parseLong(System.getProperty(OMSConst.SYS_PROPERTY_JMS_TTL));
}
logger.info("LN:103", "==JMS Topic TTL:" + ttl);
}
#Override
public void processSendToExchange(ExchangeMessage exchangeMessage) {
sendToExchange(exchangeMessage);
}
public boolean isParallelRunEnabled() {
Object isParallelRun = beanRegistryCore.getCacheAdaptorI().cacheGet(OMSConst.DEFAULT_TENANCY_CODE, OMSConst.APP_PARAM_IS_PARALLEL_RUN, CACHE_NAMES.SYS_PARAMS_CACHE_CORE);
if (isParallelRun != null && String.valueOf(isParallelRun).equals(OMSConst.STRING_1)) {
return true;
}
return false;
}
#Override
public void sendToExchange(ExchangeMessage exchangeMessage) {
MessageProducer producer = null;
try {
if (isParallelRunEnabled()) {
logger.info("LN:66", "== Message send to exchange skipped,due to parallel run enabled");
return;
}
if (connection == null) {
connection = factory.createConnection();
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(targetQueue);
producer.setDisableMessageID(true);
Message message = beanRegistryCore.getJmsExchangeMsgTransformerI().transformToJMSMessage(session, exchangeMessage);
producer.send(message);
producer.setTimeToLive(ttl);//default 15min
logger.elkLog("78", "-1", LogEventsEnum.SENT_TO_EXCHANGE, exchangeMessage.toString());
} catch (Exception e) {
logger.error("LN:80", " Error when sending order to exchange:", e);
throw new OMSCoreRuntimeException(e.getMessage(), e);
} finally {
try {
if (producer != null)
producer.close();
} catch (JMSException e) {
logger.error("LN:87", "JMS producer close error:", e);
}
try {
if (session != null)
session.close();
} catch (JMSException e) {
logger.error("LN:93", "JMS session close error:", e);
}
}
}
#Override
public void processSendToExchangeSync(ExchangeMessage exchangeMessage) {
}
#Override
public BeanRegistryCore getBeanRegistryCore() {
return beanRegistryCore;
}
#Override
public void setBeanRegistryCore(BeanRegistryCore beanRegistryCore) {
this.beanRegistryCore = beanRegistryCore;
}
#Override
public ConnectionFactory getFactory() {
return factory;
}
#Override
public void setFactory(ConnectionFactory factory) {
this.factory = factory;
}
#Override
public Queue getTargetQueue() {
return targetQueue;
}
#Override
public void setTargetQueue(Queue targetQueue) {
this.targetQueue = targetQueue;
}
}
But when i execute moderated code it gives me following error
javax.ejb.EJBTransactionRolledbackException: Producer is closed
Any possible fixes?
After a deep search deep into the problem, I found this https://developer.jboss.org/wiki/ShouldICacheJMSConnectionsAndJMSSessions article posted on one of JBOSS developer thread. This explains clearly the reason for caching connection and other JMS related resources being an anti-pattern for JMS code is running in a JEE application server.
In nutshell JCA layer pools JMS connections and JMS sessions. So when you call createConnection() or createSession(), then, in most cases it's not really calling the actual JMS implementation to actually create a new JMS connection or JMS session, it's just returning one from its own internal cache.
Additionally JBOSS server too manages stateless session bean pool. A stateless session bean is available on the connection pool only after you are done with the purpose of it, but not prior. Meantime Connection (Either JMS newly created or Cached) used to create JMS Session (session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) inside stateless session bean, also done with its purpose and too available on JCA layer connection pool. Therefore calling cached connection inside stateless EJB class as follow will not give you an exception even though it is not recommended by Oracle.
public void sendToExchange(ExchangeMessage exchangeMessage) {
MessageProducer producer = null;
try {
if (isParallelRunEnabled()) {
logger.info("LN:66", "== Message send to exchange skipped,due to parallel run enabled");
return;
}
if (connection == null) {
connection = factory.createConnection();
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(targetQueue);
producer.setDisableMessageID(true);
Message message = beanRegistryCore.getJmsExchangeMsgTransformerI().transformToJMSMessage(session, exchangeMessage);
producer.send(message);
producer.setTimeToLive(ttl);//default 15min
logger.elkLog("78", "-1", LogEventsEnum.SENT_TO_EXCHANGE, exchangeMessage.toString());
} catch (Exception e) {
logger.error("LN:80", " Error when sending order to exchange:", e);
throw new OMSCoreRuntimeException(e.getMessage(), e);
} finally {
try {
if (producer != null)
producer.close();
} catch (JMSException e) {
logger.error("LN:87", "JMS producer close error:", e);
}
try {
if (session != null)
session.close();
} catch (JMSException e) {
logger.error("LN:93", "JMS session close error:", e);
}
}
}
But in this case, since the same POJO class instance can be used on multiple occasions as bellow. It does not guarantee that the connection is freed and available in the JCA layer connection pool and gives exceptions.
#PostConstruct
public void init() {
beanRegistryCore = omsRegistryBean.registry();
if (exchangeSenderFacadeCore == null) {
exchangeSenderFacadeCore = ((BeanRegistryCore) omsRegistryBean.registry()).getExchangeSenderFacadeCoreI();
exchangeSenderFacadeCore.setBeanRegistryCore(omsRegistryBean.registry());
exchangeSenderFacadeCore.setFactory(factory);
exchangeSenderFacadeCore.setTargetQueue(target);
}
}

Error while sending JMS(message) with jboss EAP 7

Using Wildfly and JMS via ActiveMQ I got following exception.
javax.ejb.EJBTransactionRolledbackException: Producer is closed
I have the following stateless bean
#Stateless(name = "ExchangeSenderFacadeBean")
#Local({ExchangeSenderFacadeLocalI.class})
public class ExchangeSenderFacadeWrapperBean implements ExchangeSenderFacadeLocalI {
#Resource(lookup = "java:/JmsXA") // inject ConnectionFactory (more)
protected ConnectionFactory factory;
#EJB(beanName = "BeanRegistryLoader")
protected BeanRegistryLoader omsRegistryBean;
protected BeanRegistryCore beanRegistryCore;
#Resource(lookup = "java:/jms/queue/ToExchange")
protected Queue target;
private ExchangeSenderFacadeCoreI exchangeSenderFacadeCore;
#Override
public void sendToExchange(ExchangeMessage exchangeMessage) {
exchangeSenderFacadeCore.sendToExchange(exchangeMessage);
}
#PostConstruct
public void init() {
beanRegistryCore = omsRegistryBean.registry();
if (exchangeSenderFacadeCore == null) {
exchangeSenderFacadeCore = ((BeanRegistryCore) omsRegistryBean.registry()).getExchangeSenderFacadeCoreI();
exchangeSenderFacadeCore.setBeanRegistryCore(omsRegistryBean.registry());
exchangeSenderFacadeCore.setFactory(factory);
exchangeSenderFacadeCore.setTargetQueue(target);
}
}
}
And I use simple java class to create a method which produces a message and send it to the destination as follow
public class ExchangeSenderFacadeCore implements ExchangeSenderFacadeCoreI {
private static final OMSLogHandlerI logger = new Log4j2HndlAdaptor("ExchangeSenderFacadeCore");
private BeanRegistryCore beanRegistryCore;
private ConnectionFactory factory;
private Connection connection = null;
private Session session = null;
private long ttl = 900000;
protected Queue targetQueue;
public ExchangeSenderFacadeCore() {
if (System.getProperty(OMSConst.SYS_PROPERTY_JMS_TTL) != null && System.getProperty(OMSConst.SYS_PROPERTY_JMS_TTL).length() > 0) {
ttl = Long.parseLong(System.getProperty(OMSConst.SYS_PROPERTY_JMS_TTL));
}
logger.info("LN:103", "==JMS Topic TTL:" + ttl);
}
#Override
public void processSendToExchange(ExchangeMessage exchangeMessage) {
sendToExchange(exchangeMessage);
}
public boolean isParallelRunEnabled() {
Object isParallelRun = beanRegistryCore.getCacheAdaptorI().cacheGet(OMSConst.DEFAULT_TENANCY_CODE, OMSConst.APP_PARAM_IS_PARALLEL_RUN, CACHE_NAMES.SYS_PARAMS_CACHE_CORE);
if (isParallelRun != null && String.valueOf(isParallelRun).equals(OMSConst.STRING_1)) {
return true;
}
return false;
}
#Override
public void sendToExchange(ExchangeMessage exchangeMessage) {
MessageProducer producer = null;
try {
if (isParallelRunEnabled()) {
logger.info("LN:66", "== Message send to exchange skipped,due to parallel run enabled");
return;
}
if (connection == null) {
connection = factory.createConnection();
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(targetQueue);
producer.setDisableMessageID(true);
Message message = beanRegistryCore.getJmsExchangeMsgTransformerI().transformToJMSMessage(session, exchangeMessage);
producer.send(message);
producer.setTimeToLive(ttl);//default 15min
logger.elkLog("78", "-1", LogEventsEnum.SENT_TO_EXCHANGE, exchangeMessage.toString());
} catch (Exception e) {
logger.error("LN:80", " Error when sending order to exchange:", e);
throw new OMSCoreRuntimeException(e.getMessage(), e);
} finally {
try {
if (producer != null)
producer.close();
} catch (JMSException e) {
logger.error("LN:87", "JMS producer close error:", e);
}
try {
if (session != null)
session.close();
} catch (JMSException e) {
logger.error("LN:93", "JMS session close error:", e);
}
}
}
#Override
public void processSendToExchangeSync(ExchangeMessage exchangeMessage) {
}
#Override
public BeanRegistryCore getBeanRegistryCore() {
return beanRegistryCore;
}
#Override
public void setBeanRegistryCore(BeanRegistryCore beanRegistryCore) {
this.beanRegistryCore = beanRegistryCore;
}
#Override
public ConnectionFactory getFactory() {
return factory;
}
#Override
public void setFactory(ConnectionFactory factory) {
this.factory = factory;
}
#Override
public Queue getTargetQueue() {
return targetQueue;
}
#Override
public void setTargetQueue(Queue targetQueue) {
this.targetQueue = targetQueue;
}
}
ExchangeSenderFacadeCoreI is interface class but when I execute this code I get above exception but if I move sendToExchange() method in ExchangeSenderFacadeCore to ExchangeSenderFacadeWrapperBean class then the error will disappear. Can anyone tell me the exact reason for this scenario
After a deep search deep into the problem, I found this
https://developer.jboss.org/wiki/ShouldICacheJMSConnectionsAndJMSSessions article posted on one of JBOSS developer thread. This explains clearly the reason for caching connection and other JMS related resources being an anti-pattern for JMS code is running in a JEE application server.
In nutshell JCA layer pools JMS connections and JMS sessions. So when you call createConnection() or createSession(), then, in most cases it's not really calling the actual JMS implementation to actually create a new JMS connection or JMS session, it's just returning one from its own internal cache.
Additionally JBOSS server too manages stateless session bean pool. A stateless session bean is available on the connection pool only after you are done with the purpose of it, but not prior. Meantime Connection (Either JMS newly created or Cached) used to create JMS Session (session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) inside stateless session bean, also done with its purpose and too available on JCA layer connection pool. Therefore calling cached connection inside stateless EJB class as follow will not give you an exception even though it is not recommended by Oracle.
public void sendToExchange(ExchangeMessage exchangeMessage) {
MessageProducer producer = null;
try {
if (isParallelRunEnabled()) {
logger.info("LN:66", "== Message send to exchange skipped,due to parallel run enabled");
return;
}
if (connection == null) {
connection = factory.createConnection();
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(targetQueue);
producer.setDisableMessageID(true);
Message message = beanRegistryCore.getJmsExchangeMsgTransformerI().transformToJMSMessage(session, exchangeMessage);
producer.send(message);
producer.setTimeToLive(ttl);//default 15min
logger.elkLog("78", "-1", LogEventsEnum.SENT_TO_EXCHANGE, exchangeMessage.toString());
} catch (Exception e) {
logger.error("LN:80", " Error when sending order to exchange:", e);
throw new OMSCoreRuntimeException(e.getMessage(), e);
} finally {
try {
if (producer != null)
producer.close();
} catch (JMSException e) {
logger.error("LN:87", "JMS producer close error:", e);
}
try {
if (session != null)
session.close();
} catch (JMSException e) {
logger.error("LN:93", "JMS session close error:", e);
}
}
}
But in this case, since the same POJO class instance can be used on multiple occasions as bellow. It does not guarantee that connection is freed and available in the JCA layer connection pool and gives exceptions.
#PostConstruct
public void init() {
beanRegistryCore = omsRegistryBean.registry();
if (exchangeSenderFacadeCore == null) {
exchangeSenderFacadeCore = ((BeanRegistryCore) omsRegistryBean.registry()).getExchangeSenderFacadeCoreI();
exchangeSenderFacadeCore.setBeanRegistryCore(omsRegistryBean.registry());
exchangeSenderFacadeCore.setFactory(factory);
exchangeSenderFacadeCore.setTargetQueue(target);
}
}

Hibernate have to wait for a few seconds before I can get the object that I just created

With this session handler:
public class SessionHandler {
private static SessionFactory DBContext;
static {
try {
DBContext = HibnerateConfiguration.config().buildSessionFactory();
}
catch(Throwable t) {
throw new ExceptionInInitializerError(t);
}
}
/*
* Returns a session anyway. If currently no session exist, open a new one;
* If there is a current session, use the existing one.
*/
#Override
public Session getSession() {
try {
return DBContext.getCurrentSession();
}
catch (HibernateException he) {
logger.error("session already exist.");
return DBContext.getCurrentSession();
}
}
public void close() {
DBContext.close();
}
}
and the following create and get methods:
public Serializable create(T type_entity) {
Session session = getSessionHandler().getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Serializable result = session.save(type_entity);
tx.commit();
return result;
} catch (HibernateException ex) {
ex.printStackTrace();
if (tx!=null) tx.rollback();
throw ex;
} finally {
getSessionHandler().close();
}
}
#SuppressWarnings("unchecked")
public T get(Serializable id) throws InvalidRequestException {
Session session = getSessionHandler().getSession();
Transaction tx = session.beginTransaction();
tx.commit();
try {
Object obj = session.get(_classtype, id);
if (obj == null) {
throw new InvalidRequestException(String.format("requested object with id %s does not exist.", id));
} else {
return (T)obj;
}
} catch(HibernateException ex) {
ex.printStackTrace();
if (tx!=null) tx.rollback();
throw ex;
} finally {
getSessionHandler().close();
}
}
When I create an object that returns me id = 4, and if immediately I make a request on browser that eventually ask for the new object of id 4, I have to wait for a few seconds (last time I tried is > 3 seconds).
When the id is returned from the create, the data should already exist. However the get returns null. I highly suspect the get is using the old cache which then is updated every a few seconds, but I have no idea how to fix it.
Let me know if any info is required and I am happy to provide them.

not able to catch org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException in Service or Facade Layer

public class AccountServiceFacade {
public void updateAccount(Account accnt) {
try {
getAccountService.updateAccount();
}
catch(HibernateOptimisticLockingFailureException e) {
e.printStackTrace();
}
}
}
public class AccountService {
public void updateAccount(Account accnt) {
try {
getAccountDAO().getHibernateTemplate().update(accnt);
System.out.println("Updated sucessfully");
} catch(HibernateOptimisticLockingFailureException e) {
e.printStackTrace();
}
}
}
I have AccountServiceFacade in transaction.
In AccountServiceFacade also my flow is not coming to catch block.
Only i am getting the exception in presentation layer that is Action class.
But i need to send a user defined message by depending on the exception comes.
So how can i get the exception in sevicefacade layer or service layer.
You can try to catch StaleObjectStateException or StaleStateException at this point.
But as you said you already have an exception in presentation layer why just not use it?
you can use this
catch (Exception e) {
if(e instanceof StaleStateException || e instanceof OptimisticLockingFailureException || e instanceof HibernateOptimisticLockingFailureException || e instanceof org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException) {
some code
}
}

Categories