Issue
Consider the code snippet below. The MQ listener does 2 activities - 1. Persist the object received in MQ 2. Send APNS notification to 100 devices.
@JmsListener(destination = "${mq.queue.name}")
public void receiveMessage(String user) throws IOException {
try {
UserDetailsVO userObject = mapper.readValue(user, UserDetailsVO.class);
String result=persistUserDetails(userObject);
if(result.equalsIgnoreCase("success")) {
userService.sendAPNS(); //Sends notification to 100 devices
}
}
catch(Exception e)
{
logger.error(Error processing MQ message);
}
}
public String persistUserDetails(UserDetailsVO userObject) {
userDao.save(); // Using hibernate method
return "success";
}
public void sendAPNS() {
// sending APNS to devices
}
Here eventhough the persistUserDetails() function called before sendAPNS(), the user object is not persisted immediately in the database. Instead, it waits for the sendAPNS() to finish the activity and then the data is persisted in table. My need is to persist immediately the user details than waiting for the entire execution completes. What changes should I make?
The JPA configuration properties are given below:
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
Solution
If you need the SQL statements to be sent to the database, you can call entityManager.flush()
after persisting. But still the transaction will not be comitted until the full executioms finishes.
If you need the database transaction to be committed before sending the messages you need to wrap the persist call within a service that starts a new transaction. In an EJB for example that would be method with transaction attribute REQUIRES_NEW
.
Answered By - areus
Answer Checked By - Pedro (JavaFixing Volunteer)