# JMS MessageListener als Thread



## Freshmaker (24. Jun 2011)

Hallo,

bisher habe ich in komplett fertigen Enterpriseumgebungen entwickelt und war nur Nutzer von JMS. In einem aktuellen Projekt muss ich allerdings die JMS-Komponenten selber schreiben. Ich möchte dabei das Publish/Subscribe Paradigma umsetzen. Was ich haben möchte, ist eine einfache Klasse die permanent auf einer Queue nach Nachrichten hört.

Das Folgende Testprogramm leistet das gewünschte:


```
import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;

public class JMSSubscriber implements MessageListener {
	
	private String destinationName = "queue/testQueue";
	private Context ic = null;
	private ConnectionFactory cf = null;
	private Connection connection = null;

	public void example() throws Exception {
		ic = getInitialContext();
		cf = (ConnectionFactory) ic.lookup("/ConnectionFactory");
		Queue queue = (Queue) ic.lookup(destinationName);
		connection = cf.createConnection();
		Session session = connection.createSession(false,
				Session.AUTO_ACKNOWLEDGE);
		connection.start();

		MessageConsumer subscriber = session.createConsumer(queue);
		subscriber.setMessageListener(this);
	}

	public static void main(String[] args) throws Exception {
		JMSSubscriber g = new JMSSubscriber();
		g.example();
		while(true) {
			try{
				Thread.sleep(500);
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static Context getInitialContext()
			throws javax.naming.NamingException {
		Properties p = new Properties();
		p.put(Context.INITIAL_CONTEXT_FACTORY,
				"org.jnp.interfaces.NamingContextFactory");
		p.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
		p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
		return new javax.naming.InitialContext(p);
	}

	public void onMessage(Message message) {
		try {
			TextMessage textMessage = (TextMessage) message;
			String text = textMessage.getText();
			System.out.println("message " + text);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
```

Es funktioniert aber nur permanent, wenn ich den Main-Thread immer schlafen lege. Ohne diesen Abschnitt läuft das Programm einfach durch und ist dann terminiert. Gibt es eine elegantere Lösung, das Programm permanent am Laufen zu halten und auf der Queue zu horchen? In den fertigen Enterpriseumgebungen musste ich nie Threads verwenden. Es hat immer gereicht, einen Listener anzulegen.


----------



## Philipp-Guest (15. Sep 2011)

Hallo Zusammen,

ich habe genau das gleiche Problem wie der Thread-Eröffner. Gibt es dazu mittlerweile eine Lösung bzw. einen guten Ansatz? Ich finde die "endlos-Sleep" Loop nämlich nicht gerade schön.

Grüße
Philipp


----------



## nocturne (15. Sep 2011)

Könnt ihr versuchen:

```
connection.start();
 
        MessageConsumer subscriber = session.createConsumer(queue);
        subscriber.setMessageListener(this);
```

mit 


```
MessageConsumer subscriber = session.createConsumer(queue);
        subscriber.setMessageListener(this);

        connection.start();
```
zu tauschen?


----------



## FArt (19. Sep 2011)

JMS Tutorial: Contents


----------

