2016-08-04 44 views
1

Ich entwickle ein Messaging-System mit ActiveMQ und Play Framework v2.4.2 (Java-Version), um E-Mails an Endbenutzer zu senden. Ich bin Neuling bei JMS/ActiveMQ-Technikern. Ich habe this Hello World example bei ActiveMQ Website als Ausgangspunkt verwendet. ActiveMQ mit Play-FrameworkJMS/ActiveMQ-Ausnahme mit Play-Framework

Ich habe wie unten eine Test-Klasse zu testen, laufen und alles war in Ordnung:

public class ActiveMQMailApp { 

    public static void main(String[] args) throws Exception { 
     setup(); 
     MailConsumer.initService(); 
     for (int i =0;i<11;i++) MailProducer.sendMail(fakeMail()); 
    } 
    public static void setup(){ 
     FakeApplication fakeApplication = Helpers.fakeApplication(); 
     Helpers.start(fakeApplication); 
    } 

    private static Mail fakeMail() throws InterruptedException { 
     Thread.sleep(1000); 
     SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss"); 
     return new Mail("[email protected]", "[email protected]", "A Test Email", "<html><body><p>Date: <b> "+sdf.format(new Date())+" </b></p></body></html>"); 
    } 

} 

Aber wenn ich genau diesen Code in Haupt App verwenden, diese Ausnahme ausgelöst:

javax.jms.JMSException: Could not create Transport. Reason: java.lang.RuntimeException: Fatally failed to create SystemUsageorg/apache/activemq/protobuf/BufferInputStream 
     at org.apache.activemq.util.JMSExceptionSupport.create(JMSExceptionSupport.java:36) 
     at org.apache.activemq.ActiveMQConnectionFactory.createTransport(ActiveMQConnectionFactory.java:332) 
     at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:345) 
     at org.apache.activemq.ActiveMQConnectionFactory.createActiveMQConnection(ActiveMQConnectionFactory.java:303) 
     at org.apache.activemq.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:243) 
     at ir.iais.salary.services.MailProducer.run(MailProducer.java:35) 
Caused by: java.lang.RuntimeException: Fatally failed to create SystemUsageorg/apache/activemq/protobuf/BufferInputStream 
     at org.apache.activemq.broker.BrokerService.getSystemUsage(BrokerService.java:1159) 
     ... 5 more 
Caused by: java.io.IOException: org/apache/activemq/protobuf/BufferInputStream 
     at org.apache.activemq.util.IOExceptionSupport.create(IOExceptionSupport.java:39) 
     ... 11 more 
Caused by: java.lang.NoClassDefFoundError: org/apache/activemq/protobuf/BufferInputStream 
     at org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter.<init>(KahaDBPersistenceAdapter.java:65) 
     ... 13 more 
Caused by: java.lang.ClassNotFoundException: org.apache.activemq.protobuf.BufferInputStream 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 

Meine MailProducer und MailConsumer Klassen sind wie diese:

public class MailProducer implements Runnable{ 
    public static final String AMQ_MAIL_QUEUE = "MAIL"; 
    public static final String BROKER_URL = "vm://localhost?broker.useJmx=false&persistent=false"; 
    private Mail mail; 

    public MailProducer(Mail mail) { 
     this.mail = mail; 
    } 

    public static void sendMail(Mail mail){ 
     Thread brokerThread = new Thread(new MailProducer(mail)); 
     brokerThread.setDaemon(false); 
     brokerThread.start(); 
    } 

    @Override 
    public void run() { 
     try { 
      // Create a ConnectionFactory 
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL); 

      // Create a Connection 
      Connection connection = connectionFactory.createConnection(); 
      connection.start(); 

      // Create a Session 
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 

      // Create the destination (Topic or Queue) 
      Destination destination = session.createQueue(AMQ_MAIL_QUEUE); 

      // Create a MessageProducer from the Session to the Topic or Queue 
      MessageProducer producer = session.createProducer(destination); 
      producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); 

      // Create a messages 
      TextMessage textMessage = session.createTextMessage(new Gson().toJson(mail)); 
      // Tell the producer to send the message 
      System.out.println("Sent message: "+ new Gson().toJson(mail) + " : " + Thread.currentThread().getName()); 
      producer.send(textMessage); 

      // Clean up 
      session.close(); 
      connection.close(); 
     } 
     catch (Exception e) { 
      System.out.println("Caught: " + e); 
      e.printStackTrace(); 
     } 
    } 
} 




public class MailConsumer implements Runnable, ExceptionListener { 
    private static final Logger logger = getLogger(MailConsumer.class); 
    private static Thread mailConsumerService; 

    public static synchronized void initService() { 
     MailConsumer mailConsumer = Play.application().injector().instanceOf(MailConsumer.class); 
     if (mailConsumerService != null) { 
      logger.info("STOPPING MailConsumer thread."); 
      mailConsumerService.interrupt(); 
     } 
     logger.info("Starting MailConsumer thread."); 
     mailConsumerService = new Thread(mailConsumer); 
     mailConsumerService.setDaemon(true); 
     mailConsumerService.setName("MailConsumer Service"); 
     mailConsumerService.start(); 
     logger.info("MailConsumer thread started."); 
    } 

    @Inject 
    private MailerClient mailerClient; 

    @Override 
    public void run() { 
     try { 
      // Create a ConnectionFactory 
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(MailProducer.BROKER_URL); 

      // Create a Connection 
      Connection connection = connectionFactory.createConnection(); 
      connection.start(); 

      connection.setExceptionListener(this); 

      // Create a Session 
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 

      // Create the destination (Topic or Queue) 
      Destination destination = session.createQueue(MailProducer.AMQ_MAIL_QUEUE); 

      // Create a MessageConsumer from the Session to the Topic or Queue 
      MessageConsumer consumer = session.createConsumer(destination); 

      while (!Thread.currentThread().isInterrupted()) { 
       // Wait for a message 
       Message message = consumer.receive(); 

       if (message instanceof TextMessage) { 
        TextMessage textMessage = (TextMessage) message; 
        String text = textMessage.getText(); 
        System.out.println("Received: " + text); 
        Mail mail = new Gson().fromJson(text, Mail.class); 
        Email email = new Email(); 
        email.setFrom(mail.getFrom()); 
        email.setTo(mail.getTo()); 
        email.setSubject(mail.getSubject()); 
        email.setBodyHtml(mail.getBodyHtml()); 
        System.out.println("sending email..."); 
        mailerClient.send(email); 
        System.out.println("email sent!"); 
       } else { 
        System.out.println("Received: " + message); 
        logger.info("message type: "+message.getClass().getSimpleName()); 
       } 

      } 
      logger.info("MailConsumer interrupted."); 
      consumer.close(); 
      session.close(); 
      connection.close(); 
     } catch (Exception e) { 
      if (e instanceof InterruptedException) { 
       logger.info("MailConsumer thread interrupted."); 
      } else { 
       logger.error(e.getLocalizedMessage(), e); 
      } 
     } 
    } 

    public synchronized void onException(JMSException ex) { 
     System.out.println("JMS Exception occured. Shutting down client."); 
     logger.error("ErrorCode=" + ex.getErrorCode() + " , " + ex.getMessage(), ex); 
    } 
} 

Ich nenne MailProducer in Haupt-App wie folgt aus:

public Result sendTestMail(){ 
    if(!DevStatus.gI().isInDebugMode()) return badRequest("You'r not in Development Env."); 
    SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd hh:mm:ss"); 
    Mail mail = new Mail("[email protected]", "[email protected]", "A Test Email", "<html><body><p>Date: <b> " + sdf.format(new Date()) + " </b></p></body></html>"); 
    MailProducer.sendMail(mail); 
    return ok("email sent! "+ sdf.format(new Date())); 

Es scheint, das Problem ist org.apache.activemq.protobuf.BufferInputStream nicht in Classpath ist. Ich habe "org.apache.activemq.protobuf" % "activemq-protobuf" % "1.1" zu build.sbt hinzugefügt, aber nichts hat sich geändert. Ich habe ActiveMQ-Persistenz auch deaktiviert, indem ich persistent=false Broker-URI hinzugefügt habe, aber es hat nicht funktioniert.

Was kann ich tun? Ist es sogar sinnvoll, ActiveMQ mit Play Framework als JMS zu verwenden? Oder gibt es etwas besseres JMS, um mit Play Framework zu arbeiten? Was ist mit Akka? !!

Edit: Mein ActiveMQ Zusammenhang deps sind:

"org.apache.activemq" % "activemq-broker" % "5.13.4", 
    "org.apache.activemq" % "activemq-client" % "5.13.4", 
    "org.apache.activemq" % "activemq-kahadb-store" % "5.13.4", 
    "org.apache.activemq.protobuf" % "activemq-protobuf" % "1.1", 

Edit 2: Ich über Abhängigkeiten mit "org.apache.activemq" % "activemq-all" % "5.14.0" und die Haupt-App gestartet ersetzt zu arbeiten! Ich dachte zuerst das Problem wurde gelöst und ist mit den ActiveMQ-Paketen verwandt, aber ich erkannte, dass die ActiveMQMailApp-Testklasse jetzt dieselbe Ausnahme wie oben wirft! Ich habe diese Testklasse in einem neuen einfachen Maven-Projekt (kein Spiel-Framework) durchgeführt und alles war in Ordnung! Ich fürchte, dieser Fehler kommt später zurück. Was passiert eigentlich ?!

+0

Bitte geben Liste Abhängigkeiten – arseniyandru

+0

ich weiß es nicht Ihre Frage nicht beantworten. Was ist der Grund dafür, Akka oder nur eine Zukunft nicht zu verwenden und damit die E-Mail zu versenden? Außerdem scheint es, dass Sie jedes Mal, wenn Ihr Thread ausgeführt wird, die activemq-Verbindungsfactory erstellen - besser, wenn Sie eine Instanz davon erhalten und diese bei Bedarf wiederverwenden.Was passiert auch, wenn Sie die activemq-all-Abhängigkeit verwenden - die Ausnahme, die Sie gezeigt haben, verweist auf die fehlende Abhängigkeit von Protobuf und Kahadb (getPersistenceAdapter() von SystemUsage). Deaktivieren Sie die Persistenz für den Moment, bis die App funktioniert und greifen Sie dann auf Persistenz zurück. –

+1

@youhans Nur um sicher zu gehen: hast du 'sbt update' oder' activator update' ausgeführt? In Bezug auf die Akka/ActiveMQ-Frage, siehe [this] (http://stackoverflow.com/questions/5693346/when-to-use-actors-inst-of-messaging-solutions-such-as-websphere-mq-or -tibco) hilft. Wenn Sie ActiveMQ nicht verwenden müssen, sollten Sie Akka einen Versuch geben – Salem

Antwort

1

Fügen Sie diese Abhängigkeit zu Ihrem Pom hinzu.

<dependency> 
     <groupId>org.apache.activemq</groupId> 
     <artifactId>activemq-kahadb-store</artifactId> 
     <scope>runtime</scope> 
    </dependency> 

Siehe this Problembericht.

+0

Ich habe 'activemq-kahadb-store' Abhängigkeit zu' "org.apache.activemq"% "activemq-kahadb-store"% "5.13.4"% "runtime" 'geändert, aber es hat nicht funktioniert. – youhans

+0

Ich musste auch Version in der obigen Abhängigkeit angeben $ {activemq.version}

1

Dieses Problem wird wegen sbt eingeführt, der efeu als Auflösungssystem benutzt, und aus irgendeinem Grund activemq-protobuf entschieden Gebrauchspackungart maven-plugins.

Während Maven Entschlossenheit solcher Artefakt wie ein Gefäß für die Kompilierung, Efeu (oder ist es, weil sbt ich bin nicht wirklich sicher) wird diese als Typ löst maven-plugins anstelle des Typs jar, daher sbt wird diese Abhängigkeit ignorieren, da es kein Glas ist in diese Abhängigkeit.

Die Art und Weise, es zu beheben ist explizit ein Glas Typ Artefakt vorstellen:

libraryDependencies += "org.apache.activemq.protobuf" % "activemq-protobuf" % "1.1" jar() 
+0

Sehr hilfreich, danke! – Olaf