EntityManager in MessageListener

Hallo,

ich habe ein Problem mit dem Einfügen eines EntityManager in ein MessageListener.
Der EntityManager ist immer null. Ich gehe davon aus, das dies davon kommt, das ich den MessageListener mittels “new” selber erzeuge. Weiß aber nicht wie es anders gehen soll.

import javax.inject.Inject;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.InitialContext;


public class PODQueueWorker {
    private InitialContext initialContext = null;
    private QueueConnectionFactory queueConnectionFactory = null;
    private Queue queue = null;
    private QueueConnection queueConnection = null;
    private QueueSession queueSession = null;
    private MessageConsumer consumer = null;

    public PODQueueWorker(String name) {
	try {
		this.initialContext = new InitialContext();
		this.queueConnectionFactory = (QueueConnectionFactory) initialContext
				.lookup("java:/ConnectionFactory");

		// Die konfigurierte Queue holen:
		this.queue = (Queue) initialContext.lookup(podQueueSender.WORKER_QUEUE);

		// Verbindung erzeugen:
		// Hier muss der User angegeben werden!
		this.queueConnection = queueConnectionFactory.createQueueConnection();
		this.queueSession = queueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
		
		this.consumer = queueSession.createConsumer(queue);
		
		this.consumer.setMessageListener(new PODMessageListener(name));

		
		this.queueConnection.start();
		System.out.println("Worker gestartet");
	} catch (Exception ex) {
		ex.printStackTrace();
	}
    }

    public void stop() {
	if(this.consumer != null) {
		try {
			this.consumer.close();
		} catch (JMSException e) {
		}
		this.consumer = null;
	}
	
	if(this.queueSession != null) {
		try {
			this.queueSession.close();
		} catch (JMSException e) {
		}
		this.queueSession = null;
	}

	if(this.queueConnection != null) {
		try {
			this.queueConnection.close();
		} catch (JMSException e) {
		}
		this.queueConnection = null;
	}
    }

}




import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class PODMessageListener implements MessageListener {


    @PersistenceContext(unitName = "syscontrol")
    EntityManager em;

    private String consumerName;

    public PODMessageListener(String consumerName) {
        this.consumerName = consumerName;
        System.out.println(this.em);
    }


    @Override
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;
        try {
            System.out.println(this.em); // ist immer null
            System.out.println(consumerName + " received " + textMessage.getText());
            message.acknowledge();
        } catch (JMSException | InterruptedException e) {          
            e.printStackTrace();
        }
    }

    public String getConsumerName() {
        return this.consumerName;
    } 
}

Hätte ihr eine Idee, was ich verändern muss, damit der EntityManager nicht mehr null ist?

Danke!

Er wird ja gar nicht initialisiert, oder schaue ich nur falsch?

Wie meinst du das, das es nicht initialisiert ist? Das übernimmt doch der Server selber!?
In einer Testklasse, welche mittelst Singelton und Startup notiert ist, wird der EntityManager sauber eingefügt und kann problemlos verwendet werden.

Wenn irgendwelche “Magie” ihn initialisiert, dann offenbar zu spät, jedenfalls nach dem Aufruf von onmessage(). Dann solltest du schauen, was da hinter den Kulissen genau passiert und ob du vielleicht irgendetwas in der Reihenfolge vertauschen kannst, damit es funktioniert.

Ich habe jetzt mal ein wenig experimentiert. In einem Test habe den PODQueueWorker mit dem PODMessageListener kombiniert. Das hat ersteinmal keine Besserung gebracht.
Erst als ich den PODQueueWorker, welcher nun den PODMessageListener beinhaltet, mittels

@Startup
@Singleton
public class PODQueueWorker implements MessageListener {

notiert habe und die PODQueueWorker nicht mehr mittels

this.worker.add(new PODQueueWorker("Worker_" + String.valueOf(i)));

in einem Manager initalisiere, ist der EntityManager initalisiert.

Leider kann ich jetzt nur eine Instanz des PODQueueWorker instanzieren. Ich hätte das aber lieber dynamsich.

Also,

wenn Du DI nutzen möchtest, musst Du die Beans natürlich vom Container erzeugen lassen. Ein new() ist da immer falsch.

Was bedeutet für Dich “dynamisch”? Ich nehem an, Du bist im JEE-Umfeld unterwegs. Da gibt es auf die Annotation @Stateless.

Hallo Sym,

ja ich bin im Java EE Umfeld unterwegs, aber mein Wissen rund um Java EE ist noch recht begrenzt.
Wäre der folgende Code dann der richtige Weg um die Instanz(en) zu erzeugen?

private Instance<PODQueueWorker> podQueueWorkerInstances;

@Inject
Bean(@Any Instance<PODQueueWorker> podQueueWorkerInstances){
    this.podQueueWorkerInstances = podQueueWorkerInstances;
}

public void use(){
    PODQueueWorker newInst = this.podQueueWorkerInstances.get();

}

Kannst Du ein ganzes Codebeispiel dazu posten? Das macht es einfacher. :slight_smile: