0

I've created a web app using Java and Maven (here is my project: https://github.com/lkobylanski/Parking_Book_System_Java). Its simple parking space reservation system. It works perfectly fine on my local tomcat. However when I deployed it on Heroku using WAR deployment: https://devcenter.heroku.com/articles/war-deployment

The application runs, but I am getting 500 Server error every time I try to do anything with DB e.g. add new reservation or get API whether it will be a particular parking spot or globally all reservation. Here is the error:

HTTP Status 500 – Internal Server Error

Type Exception Report

Message java.lang.IllegalStateException: Could not initialize database

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

javax.servlet.ServletException: java.lang.IllegalStateException: Could not initialize database
    com.pbs.web.jdbc.ParkingBookSystem.BookControllerServlet.init(BookControllerServlet.java:40)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:748)

Root Cause

java.lang.IllegalStateException: Could not initialize database
    com.pbs.web.jdbc.ParkingBookSystem.BookDbUtil.<init>(BookDbUtil.java:27)
    com.pbs.web.jdbc.ParkingBookSystem.BookControllerServlet.init(BookControllerServlet.java:37)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:748)

Root Cause

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
    javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
    javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
    javax.naming.InitialContext.lookup(InitialContext.java:417)
    com.pbs.web.jdbc.ParkingBookSystem.BookDbUtil.<init>(BookDbUtil.java:24)
    com.pbs.web.jdbc.ParkingBookSystem.BookControllerServlet.init(BookControllerServlet.java:37)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:748)

Note The full stack trace of the root cause is available in the server logs.
Apache Tomcat/8.5.33

This is how I connect to my DB: I have a context.xml file placed in root/src/main/webapp/META-INF

It looks like it (username and pass are not real):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Context path="/ParkingSystem">
    <Resource 
        name="jdbc/ParkingBookSystem" 
        auth="Container"
        type="javax.sql.DataSource"
        maxTotal="20"
        maxIdle="5"
        maxWaitMillis="10000"
        username="username"
        password="password"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://sql2.freemysqlhosting.net:3306/sql2226123"
    />
</Context>

And here is the connection constructor method:

public BookDbUtil() {
    try {
        Context initContext = new InitialContext();
        Context envContext = (Context) initContext.lookup("java:/comp/env");
        dataSource = (DataSource) envContext.lookup("jdbc/ParkingBookSystem");
    } catch (NamingException e) {
        throw new IllegalStateException("Could not initialize database", e);
    }
}

EDIT: I've mae following steps:

  1. Run: heroku config:set WEBAPP_RUNNER_OPTS="--enable-naming --context-xml=C:\context\context.xml added real path to my context.xml
  2. Use following command: heroku war:deploy D:\Luki\Archiwum\WARfiles\ParkingBookSystem.war --includes context.xml

And getting following error:

Uploading ParkingBookSystem.war
-----> Packaging application...
       - app: parking-booking
       - including: context.xml
 ! ERROR: There was an error packaging the application for deployment.
 !        Re-run with HEROKU_DEBUG=1 for more info.
 !    There was a problem deploying to parking-booking.
 !    Make sure you have permission to deploy by running: heroku apps:info -a parking-booking
Luke_Nuke
  • 461
  • 2
  • 6
  • 23
  • 1
    How are you trying to connect to your database? (Please [edit] your question and add the relevant code. We shouldn't have to go off-site to understand your question.) – ChrisGPT was on strike Oct 08 '18 at 19:21
  • Why are you `freemysqlhosting.net` instead of one of the [Heroku addons](https://elements.heroku.com/addons) that provides MySQL? – ChrisGPT was on strike Oct 08 '18 at 19:54
  • Because when I was creating project I didn't even know about heroku. Anyway if the mySQL server is valid and the data is valid shouldn't it work? – Luke_Nuke Oct 08 '18 at 20:21
  • I'm not sure. I've never heard for `freemysqlhosting.net` and it looks pretty amateur. Who knows how they run their services? And clearly there's an issue connecting. But anyway, why should it matter if you knew about Heroku when you created the project? Surely your database configuration can be changed from environment to environment? – ChrisGPT was on strike Oct 08 '18 at 20:23
  • Yes, it probably can :) I never did anything like that so far. So I can just export ma table, and import to heroku and then just change the DB data in context.xml and it should work? However, I was just curious why it does not work now. – Luke_Nuke Oct 08 '18 at 21:00
  • Possible duplicate of [NoInitialContextException error](https://stackoverflow.com/questions/1525385/noinitialcontextexception-error) – ChrisGPT was on strike Oct 08 '18 at 21:02
  • I'm not sure why it doesn't work now. I'm pretty good with Heroku, but I don't work much with Java. Maybe the question I just suggested as a duplicate will help? – ChrisGPT was on strike Oct 08 '18 at 21:03

1 Answers1

1

You'll need to add the Tomcat webapp-runner options --enable-naming and --context-xml=path/to/context.xml to your WEBAPP_RUNNER_OPTS like this:

$ heroku config:set WEBAPP_RUNNER_OPTS="--enable-naming --context-xml=path/to/context.xml"

You'll need the context.xml to be a file outside of the WAR, and you'll need to include with the --include option in the Heroku Java CLI.

codefinger
  • 10,088
  • 7
  • 39
  • 51
  • Hey I've updated my question since I've made the steps u showed me but I've stuck. I've tried use include as edited in my question. Also tried 1st deploy the WAR file then include context.xml. I can't find what is wrong. – Luke_Nuke Oct 09 '18 at 13:40