What am i trying to accomplish:
I have a JMS queue and I want to asynchronously get elements from that queue and send to a Printer. This printer is very specific and dumb so it can't queue on it's on or buffer anything at all. I must perform 5 steps in sequence on this printer and the steps of a queued elemet must not overlap the steps of another element. For each step the printer will return 1 on success and another number on failure.
The current implementation is an MDB with an onMessage method call to a @Lock(LockType.WRITE) method from a Singleton ejb.
The MDB:
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup",
propertyValue = "jms/MyQueue"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")})
public class SimpleMessageBean implements MessageListener {
@Resource
private MessageDrivenContext mdc;
static final Logger logger = Logger.getLogger("SimpleMessageBean");
@EJB
private Print print;
public SimpleMessageBean() {
}
@Override
public void onMessage(Message inMessage) {
try {
if (inMessage instanceof TextMessage) {
logger.log(Level.INFO, "MESSAGE BEAN: Message received: {0}", inMessage.getBody(String.class));
String params[] = ((TextMessage) inMessage).getText().split("\\s+");
print.doStuff(params[0], params[1]);
} else {
logger.log(Level.WARNING,"Error")
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Rollback Happening: {0}", e.toString());
mdc.setRollbackOnly();
}
}
The Singleton:
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Startup
@Singleton
@AccessTimeout(value = 120000)
public class Print {
static final Logger logger = Logger.getLogger("SimpleMessageBean");
public Print() {
}
@Lock(LockType.WRITE)
public void doStuff(String cpf, String value) throws Exception{
try{
int return;
return = Bematech.AbreCupom(cpf);
System.out.println("Stage0 = " + return);
return = Bematech.VendeItem("111112", "Parking", "FF", "hours", "1", 2, value, "%", "00,00");
System.out.println("Stage1 = " + return);
return = Bematech.IniciaFechamentoCupom("D", "%", "00,00");
System.out.println("Stage2 = " + return);
return = Bematech.EfetuaFormaPagamento("Dinheiro", value);
System.out.println("Stage3 = " + return);
return = Bematech.TerminaFechamentoCupom("Thankyou ofr your support");
System.out.println("Stage4 = " + return);
}catch ( Exception MensagemErro ){
throw MensagemErro;
}
}
I expected this implementation to receive the data from the queue and print it one element at a time as the doStuff() method is locked, AKA:
Stage0=1
Stage1=1
Stage2=1
Stage3=1
Stage4=1
Stage0=1
Stage1=1
Stage2=1
Stage3=1
Stage4=1
Stage0=1
...
But sometimes (seems to be random but it happens more often when several messages are queued at once) i get two concurrent access to the print method:
Stage0=1
Stage1=1
Stage0=1
Stage2=1
Stage1=1
Stage3=1
Stage2=1
...
From what is being print I can see that 2 elements are overlapping in the printer access.
Usefull info:
Java EE 7. Glassfish 4-0. Not Using JBOSS.
Any ideas why this is happening?