java.lang.ClassNotFoundException: org.zeromq.ZContext при попытке запустить службу Windows

У меня есть базовое java-приложение Maven, которое я создал, и оно зависит от JeroMQ, который является полной Java-реализацией ZeroMQ. Поскольку мне также нужно обернуть это java-приложение как службу Windows, я решил использовать Apache Commons Daemon и, в частности, последовал этому прекрасному примеру: http://web.archive.org/web/20090228071059/http://blog.platinumsolutions.com/node/234 Вот как выглядит код Java:

package com.org.SubscriberACD;

import java.nio.charset.Charset;

import org.zeromq.ZContext;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Socket;

/**
 * JeroMQ Subscriber for Apache Commons Daemon
 *
 */
public class Subscriber 
{
    /**
    * Single static instance of the service class
    */
    private static Subscriber subscriber_service = new Subscriber();

    /**
     * Static method called by prunsrv to start/stop
     * the service.  Pass the argument "start"
     * to start the service, and pass "stop" to
     * stop the service.
     */
    public static void windowsService(String args[]) {
       String cmd = "start";
       if(args.length > 0) {
          cmd = args[0];
       }

       if("start".equals(cmd)) {
          subscriber_service.start();
       }
       else {
          subscriber_service.stop();
       }
    }

    /**
     * Flag to know if this service
     * instance has been stopped.
     */
    private boolean stopped = false;


    /**
     * Start this service instance
     */
    public void start() {

       stopped = false;

       System.out.println("My Service Started "
                          + new java.util.Date());

       ZContext context = new ZContext();

       Socket subscriber = context.createSocket(ZMQ.SUB);
       subscriber.connect("tcp://localhost:5556");
       String subscription = "MySub";
       subscriber.subscribe(subscription.getBytes(Charset.forName("UTF-8")));

       while(!stopped) {
          System.out.println("My Service Executing "
                              + new java.util.Date());

          String topic = subscriber.recvStr();
          if (topic == null)
              break;
          String data = subscriber.recvStr();
          assert(topic.equals(subscription));
          System.out.println(data);

          synchronized(this) {
             try {
                this.wait(60000);  // wait 1 minute
             }
             catch(InterruptedException ie){}
          }
       }

       subscriber.close();
       context.close();
       context.destroy();

       System.out.println("My Service Finished "
                           + new java.util.Date());
    }

    /**
     * Stop this service instance
     */
    public void stop() {
       stopped = true;
       synchronized(this) {
          this.notify();
       }
    }
 }

Затем я создал следующую структуру папок, как было предложено в руководстве:

E:\SubscriberACD
   \bin
        \subscriberACD.exe
        \subscriberACDw.exe
   \classes
        \com\org\SubscriberACD\Subscriber.class
   \logs

Затем я перешел в каталог bin и ввел следующую команду для установки службы:

subscriberACD.exe //IS//SubscriberACD --Install=E:\SubscriberACD\bin\subscriberACD.exe --Descriptio
n="Subscriber using Apache Commons Daemon" --Jvm=c:\glassfish4\jdk7\jre
\bin\server\jvm.dll --Classpath=E:\SubscriberACD\classes --StartMode=jvm
 --StartClass=com.org.SubscriberACD.Subscriber --StartMethod=windowsSer
vice --StartParams=start --StopMode=jvm --StopClass=com.org.SubscriberA
CD.Subscriber --StopMethod=windowsService --StopParams=stop --LogPath=E:\SubscriberACD\logs --StdOutput=auto --StdError=auto

Установка работает нормально, так как я вижу ее в службах Windows. Однако, когда я пытаюсь запустить его оттуда, я получаю сообщение об ошибке «Windows не может запустить SubscriberACD на локальном компьютере».

Я проверил журналы ошибок и увидел следующую запись:

2016-04-14 14:38:40 Commons Daemon procrun stderr initialized
Exception in thread "main" ror: org/zeromq/ZContext
    at com.org.SubscriberACD.Subscriber.start(Subscriber.java:57)
    at com.org.SubscriberACD.Subscriber.windowsService(Subscriber.java:33)
Caused by: java.lang.ClassNotFoundException: org.zeromq.ZContext
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    ... 2 more

Стоит отметить, что JeroMQ в настоящее время является банкой в ​​моих зависимостях Maven. Я настроил его из своего файла POM.xml.

Я думаю, проблема может заключаться в том, что у моей службы нет доступа к банке JeroMQ, которая находится в моих зависимостях Maven. Я предполагаю, что файл класса не содержит зависимостей. Итак, я попытался экспортировать весь свой проект в виде банки и поместил этого ребенка под E:\SubscriberACD\classes\. Итак, моя структура теперь выглядит так:

E:\SubscriberACD
   \bin
        \subscriberACD.exe
        \subscriberACDw.exe
   \classes
        \com\org\SubscriberACD\
             \Subscriber.class
        \Subscriber.jar
   \logs

Однако это не решило проблему. Может кто-нибудь пролить некоторый свет на это?


person SpartaSixZero    schedule 14.04.2016    source источник


Ответы (1)


Измените аргумент --Classpath на:

--Classpath=E:\SubscriberACD\classes\your-jar-filename.jar 

У вас почти наверняка есть другие jar-файлы, которые вам понадобятся, поэтому просто добавьте их в конец --Classpath, используя ; (точка с запятой) разделители...

--Classpath=E:\SubscriberACD\classes\your-jar-filename.jar;e:\other-dir\classes\some-other.jar;etc...
person lincolnadym    schedule 14.04.2016
comment
Спасибо, работает как шарм! Что я сделал, так это использовал путь к банку, который я создал, он же Subscriber.jar, а затем я добавил файл jar для JeroMQ, который был в моих зависимостях, также известный как jeromq-0.3.5.jar. Конечно, мне пришлось найти, где Eclipse хранит этот jar-файл, а затем скопировать этот jar-файл, чтобы он жил в E:\SubscriberACD\classes. - person SpartaSixZero; 15.04.2016