WAR项目中单独的应用程序逻辑线程和servlet线程

时间:2022-01-18 19:34:55

I've created a working RESTful jersey application, build as a JAR, that has a local module of classes with a main class Converter that contains functions like public static Pipe fromDNAtoRNA(String chr, int start, int end, Strand str), and has public static void main(String[] args) that runs Converter.register(), which initializes local objects using remote repositories, and Converter.runJettyServer() that creates a jetty server on port 8080.

我已经创建了一个工作的RESTful jersey应用程序,构建为JAR,它有一个带有主类Converter的本地模块类,包含来自DNAtoRNA的公共静态管道(String chr,int start,int end,Strand str),以及具有public static void main(String [] args),它运行Converter.register(),它使用远程存储库初始化本地对象,以及Converter.runJettyServer(),它在端口8080上创建一个jetty服务器。

The REST interface is in the class RestfulConverter, which just sort of wraps the functions of Converter. Here's a sample:

REST接口位于RestfulConverter类中,它只包含Converter的功能。这是一个示例:

@GET
@Path("/from/dna/chr/{chr-num}/strand/{str-type}/{start}..{end}/to/rna")
@Produces("application/javascript")
public String doDNA2RNA(@PathParam("chr-num") String chr,
        @PathParam("str-type") int str, @PathParam("start") int start,
        @PathParam("end") int end, @QueryParam("callback") String callback) {
    Pipe ans = null;
    try {
        switch (str) {
        case 1:
            ans = Converter
                    .fromDNAtoRNA(chr, start, end, Converter.FORWARD); ... }

Now I need the application to be a WAR file, which in my experience doesn't usually let the programmer define a main method.

现在我需要将应用程序作为WAR文件,根据我的经验,通常不会让程序员定义主方法。

I'm using org.glassfish.jersey.servlet.ServletContainer as a sole servlet. How should I use the Converter.register() to initialize my objects, before any one could use the REST interface?

我使用org.glassfish.jersey.servlet.ServletContainer作为唯一的servlet。在任何人使用REST接口之前,我应该如何使用Converter.register()初始化我的对象?

I've tried to extend the org.glassfish.jersey.servlet.ServletContainer with a RESTServlet class, and override the init() method like this (snippet-1):

我试图使用RESTServlet类扩展org.glassfish.jersey.servlet.ServletContainer,并覆盖这样的init()方法(snippet-1):

public void init() throws ServletException {
    super.init();
    try {
        Converter.main(null);
    } catch (DAOException e) {
        e.printStackTrace();
    }
}

But this throws java.lang.NoClassDefFoundError: org/eclipse/jetty/server/Handler

但这会抛出java.lang.NoClassDefFoundError:org / eclipse / jetty / server / Handler

How should I approach this?
What if I want to update my objects on some time interval (like using Converter.register() every 4 hours without interrupting REST interface cilents)?
How do I separate the servlet/REST logic from partitions of my application logic using different threads?
Should I define a new classloader?

我该怎么做呢?如果我想在一段时间间隔内更新我的对象(比如每4小时使用一次Converter.register()而不中断REST接口cilents)会怎么样?如何使用不同的线程将servlet / REST逻辑与应用程序逻辑的分区分开?我应该定义一个新的类加载器吗?

I have no experience with defining classloaders and multiple threads, and I've tried to look for tutorials, but didn't find anything that can help my particular situation.

我没有定义类加载器和多线程的经验,我试图寻找教程,但没有找到任何可以帮助我的特定情况的东西。

EDIT
Here's the full error log after regarding snippet-1 :

编辑这是关于代码段-1后的完整错误日志:

May 06, 2015 1:15:36 PM org.apache.catalina.core.ApplicationContext log
SEVERE: StandardWrapper.Throwable
java.lang.NoClassDefFoundError: org/eclipse/jetty/server/Handler
    at il.ac.ariel.concord.service.RESTServlet.init(RESTServlet.java:16)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1144)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:817)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1517)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1474)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.server.Handler
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
    ... 22 more

May 06, 2015 1:15:36 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Allocate exception for servlet Extended Jersey
java.lang.ClassNotFoundException: org.eclipse.jetty.server.Handler
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
    at il.ac.ariel.concord.service.RESTServlet.init(RESTServlet.java:16)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1144)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:817)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1517)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1474)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

EDIT 2:
After eliminating previous imports of jetty server on the Converter class, snippet-1 worked fine.

编辑2:在转换类上删除以前导入的jetty服务器之后,snippet-1工作正常。

1 个解决方案

#1


Have a look at http://blog.eisele.net/2010/12/seven-ways-to-get-things-started-java.html in particular the bit on Startup Servlets

看看http://blog.eisele.net/2010/12/seven-ways-to-get-things-started-java.html,特别是关于Startup Servlets的一点

@Startup Servlet

The old fashioned way. You can do whatever logic is needed within your startup servlet. This is a simple servlet in general which gets a >load-on-startup< parameter in your web.xml or the @WebServlet(name="startup", loadOnStartup="2") annotation. This servlet has a load-at-startup priority of 2, meaning any servlet with a load priority lower than 2 will be loaded before this one, and those greater than 2 after. If you have an init() method which is called by the servlet container to indicate to a servlet that the servlet is being placed into service and a destroy() method which is called by the servlet container to indicate to a servlet that the servlet is being taken out of service.

老式的方式。您可以在启动servlet中执行任何需要的逻辑。这是一个简单的servlet,它在web.xml中获取> load-on-startup <参数或@webservlet(name =“startup”,loadonstartup="“2”)注释。此servlet的启动时加载优先级为2,这意味着任何负载优先级低于2的servlet将在此之前加载,而之后大于2的servlet将加载。如果你有一个init()方法,servlet容器调用它来向servlet指示servlet正在进入服务,并且servlet容器调用一个destroy()方法来向servlet指示servlet是被取消服务。

public class StartupServlet extends javax.servlet.http.HttpServlet {

public class StartupServlet扩展了javax.servlet.http.HttpServlet {

public void init(ServletConfig config) throws ServletException { .... }

public void init(ServletConfig config)抛出ServletException {....}

public void destroy() { .... } }

public void destroy(){....}}

If you want to do things on a timed basis, you should look into the @Timeout annotation http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html though this only works on a full Java EE application server like Wildfly

如果你想在定时的基础上做事,你应该查看@Timeout注释http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html,虽然这只适用于完整的Java EE应用程序像Wildfly这样的服务器

#1


Have a look at http://blog.eisele.net/2010/12/seven-ways-to-get-things-started-java.html in particular the bit on Startup Servlets

看看http://blog.eisele.net/2010/12/seven-ways-to-get-things-started-java.html,特别是关于Startup Servlets的一点

@Startup Servlet

The old fashioned way. You can do whatever logic is needed within your startup servlet. This is a simple servlet in general which gets a >load-on-startup< parameter in your web.xml or the @WebServlet(name="startup", loadOnStartup="2") annotation. This servlet has a load-at-startup priority of 2, meaning any servlet with a load priority lower than 2 will be loaded before this one, and those greater than 2 after. If you have an init() method which is called by the servlet container to indicate to a servlet that the servlet is being placed into service and a destroy() method which is called by the servlet container to indicate to a servlet that the servlet is being taken out of service.

老式的方式。您可以在启动servlet中执行任何需要的逻辑。这是一个简单的servlet,它在web.xml中获取> load-on-startup <参数或@webservlet(name =“startup”,loadonstartup="“2”)注释。此servlet的启动时加载优先级为2,这意味着任何负载优先级低于2的servlet将在此之前加载,而之后大于2的servlet将加载。如果你有一个init()方法,servlet容器调用它来向servlet指示servlet正在进入服务,并且servlet容器调用一个destroy()方法来向servlet指示servlet是被取消服务。

public class StartupServlet extends javax.servlet.http.HttpServlet {

public class StartupServlet扩展了javax.servlet.http.HttpServlet {

public void init(ServletConfig config) throws ServletException { .... }

public void init(ServletConfig config)抛出ServletException {....}

public void destroy() { .... } }

public void destroy(){....}}

If you want to do things on a timed basis, you should look into the @Timeout annotation http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html though this only works on a full Java EE application server like Wildfly

如果你想在定时的基础上做事,你应该查看@Timeout注释http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html,虽然这只适用于完整的Java EE应用程序像Wildfly这样的服务器