简体   繁体   中英

Class for added dependency not found for Java Web WAR deployed to heroku tomcat

Following this tutorial here : https://devcenter.heroku.com/articles/java-webapp-runner , I changed the POM to include several dependencies and the source code (the servlet) of my web app to utilize the added dependency in the init() method to load a file. I tested the app locally using both webapp-runner and mvn heroku:run-war , and the servlets work as expected! However, when I deploy using mvn heroku:deploy-war to Heroku , and I navigate to the link after finishing deployment, I get the following error when I first opened the link :

HTTP Status 500 - Servlet.init() for servlet HelloWorld threw exception

type Exception report

message Servlet.init() for servlet HelloWorld threw exception

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Servlet.init() for servlet HelloWorld threw exception
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

root cause

java.lang.ExceptionInInitializerError
    org.nd4j.nativeblas.NativeOpsHolder.<init>(NativeOpsHolder.java:16)
    org.nd4j.nativeblas.NativeOpsHolder.<clinit>(NativeOpsHolder.java:9)
    org.nd4j.linalg.cpu.nativecpu.ops.NativeOpExecutioner.<init>(NativeOpExecutioner.java:37)
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    java.lang.Class.newInstance(Class.java:442)
    org.nd4j.linalg.factory.Nd4j.initWithBackend(Nd4j.java:5267)
    org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5183)
    org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:167)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxt(WordVectorSerializer.java:1578)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxtVectors(WordVectorSerializer.java:1502)
    herokutest.HelloWorld.init(HelloWorld.java:41)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

root cause

java.lang.RuntimeException: ND4J is probably missing dependencies. For more information, please refer to: http://nd4j.org/getstarted.html
    org.nd4j.nativeblas.NativeOps.<clinit>(NativeOps.java:39)
    org.nd4j.nativeblas.NativeOpsHolder.<init>(NativeOpsHolder.java:16)
    org.nd4j.nativeblas.NativeOpsHolder.<clinit>(NativeOpsHolder.java:9)
    org.nd4j.linalg.cpu.nativecpu.ops.NativeOpExecutioner.<init>(NativeOpExecutioner.java:37)
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    java.lang.Class.newInstance(Class.java:442)
    org.nd4j.linalg.factory.Nd4j.initWithBackend(Nd4j.java:5267)
    org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5183)
    org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:167)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxt(WordVectorSerializer.java:1578)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxtVectors(WordVectorSerializer.java:1502)
    herokutest.HelloWorld.init(HelloWorld.java:41)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

root cause

java.lang.UnsatisfiedLinkError: no jnind4j in java.library.path
    java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    java.lang.Runtime.loadLibrary0(Runtime.java:870)
    java.lang.System.loadLibrary(System.java:1122)
    org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:727)
    org.bytedeco.javacpp.Loader.load(Loader.java:502)
    org.nd4j.nativeblas.NativeOps.<clinit>(NativeOps.java:37)
    org.nd4j.nativeblas.NativeOpsHolder.<init>(NativeOpsHolder.java:16)
    org.nd4j.nativeblas.NativeOpsHolder.<clinit>(NativeOpsHolder.java:9)
    org.nd4j.linalg.cpu.nativecpu.ops.NativeOpExecutioner.<init>(NativeOpExecutioner.java:37)
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    java.lang.Class.newInstance(Class.java:442)
    org.nd4j.linalg.factory.Nd4j.initWithBackend(Nd4j.java:5267)
    org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5183)
    org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:167)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxt(WordVectorSerializer.java:1578)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxtVectors(WordVectorSerializer.java:1502)
    herokutest.HelloWorld.init(HelloWorld.java:41)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

root cause

java.lang.UnsatisfiedLinkError: no nd4j in java.library.path
    java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    java.lang.Runtime.loadLibrary0(Runtime.java:870)
    java.lang.System.loadLibrary(System.java:1122)
    org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:727)
    org.bytedeco.javacpp.Loader.load(Loader.java:493)
    org.nd4j.nativeblas.NativeOps.<clinit>(NativeOps.java:37)
    org.nd4j.nativeblas.NativeOpsHolder.<init>(NativeOpsHolder.java:16)
    org.nd4j.nativeblas.NativeOpsHolder.<clinit>(NativeOpsHolder.java:9)
    org.nd4j.linalg.cpu.nativecpu.ops.NativeOpExecutioner.<init>(NativeOpExecutioner.java:37)
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    java.lang.Class.newInstance(Class.java:442)
    org.nd4j.linalg.factory.Nd4j.initWithBackend(Nd4j.java:5267)
    org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5183)
    org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:167)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxt(WordVectorSerializer.java:1578)
    org.deeplearning4j.models.embeddings.loader.WordVectorSerializer.loadTxtVectors(WordVectorSerializer.java:1502)
    herokutest.HelloWorld.init(HelloWorld.java:41)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

Procfile

web:    java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT target/*.war

POM.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.tomcat.heroku</groupId>
  <artifactId>heroku-tomcat</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>heroku-tomcat Maven Webapp</name>
  <url>http://maven.apache.org</url>


  <properties>
    <nd4j.version>0.6.0</nd4j.version>
    <dl4j.version>0.6.0</dl4j.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>


  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.deeplearning4j</groupId>
      <artifactId>deeplearning4j-ui</artifactId>
      <version>${dl4j.version}</version>
    </dependency>

    <dependency>
      <groupId>org.deeplearning4j</groupId>
      <artifactId>deeplearning4j-nlp</artifactId>
      <version>${dl4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.nd4j</groupId>
      <artifactId>nd4j-native</artifactId>
      <version>${nd4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.nd4j</groupId>
      <artifactId>nd4j-common</artifactId>
      <version>${nd4j.version}</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>



  </dependencies>


  <build>
    <finalName>heroku-tomcat</finalName>
    <plugins>

        <plugin>
          <groupId>com.heroku.sdk</groupId>
          <artifactId>heroku-maven-plugin</artifactId>
          <version>1.1.1</version>
        </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.3</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals><goal>copy</goal></goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>com.github.jsimone</groupId>
                  <artifactId>webapp-runner</artifactId>
                  <version>8.0.30.2</version>
                  <destFileName>webapp-runner.jar</destFileName>
                </artifactItem>
              </artifactItems>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>


</project>

Source Code :

package herokutest;

import org.apache.commons.lang.math.NumberUtils;
import org.bytedeco.javacpp.presets.opencv_core;
import org.deeplearning4j.models.embeddings.loader.WordVectorSerializer;
import org.deeplearning4j.models.embeddings.wordvectors.WordVectors;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Collection;

/**
 * Created by Mr_RexZ on 10/23/2016.
 */
public class HelloWorld extends HttpServlet {

    private String message;
    String loc="/WEB-INF/glove.6B.50d.txt";


    @javax.ws.rs.core.Context
    ServletContext context;
    WordVectors wordVectors;

    public void init(final ServletConfig config) throws ServletException
    {
        message = "Hi";

        String fullPath = config.getServletContext().getRealPath(loc);
        File file = new File(fullPath);
        try {
            wordVectors = WordVectorSerializer.loadTxtVectors(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
            throws ServletException, IOException
    {

        response.setContentType("text/html");

        boolean submitSim = request.getParameter("submitSim") != null;
        boolean submitAn = request.getParameter("submitAn") != null;


        String findSim = request.getParameter("findSim");
        request.setAttribute("findSim", findSim);

        String resSim = request.getParameter("resSim");
        request.setAttribute("resSim", resSim);
        if (request.getParameter("numSim")!=null && NumberUtils.isNumber(request.getParameter("numSim"))) {
            int numSim = Integer.parseInt(request.getParameter("numSim"));
            request.setAttribute("numSim", request.getParameter("numSim"));

        if(submitSim) {
            Collection<String> lst = wordVectors.wordsNearest(findSim, numSim);
            request.setAttribute("resSim", Arrays.toString(lst.toArray()));
        }

        }
        String an1 = request.getParameter("an1");
        String an2 = request.getParameter("an2");
        String an3 = request.getParameter("an3");
        request.setAttribute("an1", an1);
        request.setAttribute("an2", an2);
        request.setAttribute("an3", an3);

        String resAn = request.getParameter("resAn");
        request.setAttribute("resAn", resAn);

        if (request.getParameter("numAn")!=null && NumberUtils.isNumber(request.getParameter("numAn"))) {
            int numAn = Integer.parseInt(request.getParameter("numAn"));
            request.setAttribute("numAn", request.getParameter("numAn"));

        if (submitAn) {
            Collection<String> lst =  wordVectors.wordsNearest(Arrays.asList(new String[] {an2,an3}) , Arrays.asList(new String[] {an1}),numAn);
            request.setAttribute("resAn", Arrays.toString(lst.toArray()));
        }
        }
        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

    public void destroy()
    {
        // do nothing.
    }
}

However, when I remove the additional dependencies, the web app works.. To my understanding, testing the app locally using web-app runner to test if the app will work is sufficient to see if it will also be functional when deployed to Heroku, as it prevents runtime issue. But I don't get it why it's not working in the case of added dependency?

Your underlying problem is actually related to the c++ code in nd4j. I'm assuming you already have a trained model which means you should be relatively familiar with an nd4j backend( http://nd4j.org/backend.html ). If that's the case make sure to add nd4j-native-platform with the latest version of nd4j to your classpath.

Nd4j native platform will bundle all of the native libraries for various platforms together.

If that doesn't work for any reason you can go the classifier route.

Read this: What is the purpose of Classifier tag in maven?

You'll see here: http://repo1.maven.org/maven2/org/nd4j/nd4j-native/0.6.0/

Look at the names of the jar files and you'll see nd4j-native- SOME CLASSIFIER HERE

Since you're deploying on linux you're going to probably want: linux-x86_64.jar

This is the OS-CHIP_ARCHITECTURE in there you'll also see mac,windows,powerpc, and android

As of this right it's 0.6.0.

The dl4j examples will always have the latest version: github.com/deeplearning4j/dl4j-examples

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM