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?