singhakash
singhakash

Reputation: 7919

Hibernate unable to create schema automatically on Heroku postgres

I have a play 2.4 hibernate postgresql application which works well locally, creates a table automatically initially. But when deployed on heroku it does not create any table though the app loaded without any errors(connected my heroku db from pgAdmin). My Configuration

build.sbt

name := "lms"

version := "1.0"

lazy val `lms` = (project in file(".")).enablePlugins(PlayJava)

scalaVersion := "2.11.7"

libraryDependencies ++= Seq(javaJdbc, cache, javaWs,
  javaJpa.exclude("org.hibernate.javax.persistence", "hibernate-jpa-2.0-api"),
  "postgresql" % "postgresql" % "9.1-901-1.jdbc4",
  "org.hibernate" % "hibernate-entitymanager" % "5.0.1.Final",
  "net.sf.dozer" % "dozer" % "5.4.0")

unmanagedResourceDirectories in Test <+= baseDirectory(_ / "target/web/public/test")

resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases"  

application.conf

# This is the main configuration file for the application.
# ~~~~~

# Secret key
# ~~~~~
# The secret key is used to secure cryptographics functions.
# If you deploy your application to several instances be sure to use the same key!
application.secret = "%APPLICATION_SECRET%"

# The application languages
# ~~~~~
application.langs = "en"

# Global object class
# ~~~~~
# Define the Global object class for this application.
# Default to Global in the root package.
# application.global=Global

# Router
# ~~~~~
# Define the Router object to use for this application.
# This router will be looked up first when the application is starting up,
# so make sure this is the entry point.
# Furthermore, it's assumed your route file is named properly.
# So for an application router like `my.application.Router`,
# you may need to define a router file `conf/my.application.routes`.
# Default to Routes in the root package (and conf/routes)
# application.router=my.application.Routes

# Database configuration
# ~~~~~
# You can declare as many datasources as you want.
# By convention, the default datasource is named `default`
#
db.default.driver=org.postgresql.Driver
db.default.url=${?DATABASE_URL}



db.default.jndiName = DefaultDS
jpa.default = defaultPersistenceUnit
db.default.hikaricp.connectionTestQuery="SELECT TRUE"
# Evolutions
# ~~~~~
# You can disable evolutions if needed
# evolutionplugin=disabled

# Logger
# ~~~~~
# You can also configure logback (http://logback.qos.ch/),
# by providing an application-logger.xml file in the conf directory.

# Root logger:
logger.root = ERROR

# Logger used by the framework:
logger.play = INFO

# Logger provided to your application:
logger.application = DEBUG


db.default.logStatements = true

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">

    <persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <non-jta-data-source>DefaultDS</non-jta-data-source>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="javax.persistence.sql-load-script-source"
                      value="META-INF/sql/data.sql"/>
        </properties>

    </persistence-unit>

</persistence>

Procfile

web: target/universal/stage/bin/lms -Dhttp.port=${PORT} -Dplay.evolutions.db.default.autoApply=true -Ddb.default.url=${DATABASE_URL}

Is there any more changes I have to do to create the database schema initially on heroku postgres? What could be the problem?

EDIT:

E:\Projects\lms\LMS>heroku buildpacks
=== leadmanagementsystem Buildpack URL
heroku/scala

E:\Projects\lms\LMS>heroku config
=== leadmanagementsystem Config Vars
DATABASE_URL: postgres://aaa:111@dasdsfsv.compute-1.amazonaws.com:5432/dfregv

E:\Projects\lms\LMS>heroku run "echo $JDBC_DATABASE_URL"
Running echo $JDBC_DATABASE_URL on leadmanagementsystem... !
 !    ENOTFOUND: getaddrinfo ENOTFOUND api.heroku.com api.heroku.com:443

Upvotes: 2

Views: 1168

Answers (4)

asch
asch

Reputation: 1963

If you use the flag

PlayKeys.externalizeResources := false

the distribution zip is created without conf folder and so META-INF/persistence.xml file is not included. I guess that in this case Play detects the JPA model by scanning for all DB annotations. If you have in conf folder configuration files, which are intended for editing on site, distribution package without conf folder is not appropriate.

To fix your DB problem without the flag PlayKeys.externalizeResources you should add you DB model mapping into persistence.xml. See the example in another answer

Upvotes: 1

singhakash
singhakash

Reputation: 7919

Finally figured out.

I dint read Play 2.4.x JavaJPA docs carefully.


Running Play in development mode while using JPA will work fine, but in order to deploy the application you will need to add this to your build.sbt file.

PlayKeys.externalizeResources := false

Adding the above line resolved the issue.

Upvotes: 0

codefinger
codefinger

Reputation: 10338

I'm not certain how Hibernate+Play works, but if I were using Hibernate in a traditional Java app, I would initialize the EntityManager like this:

Map<String, String> env = System.getenv();
Map<String, Object> configOverrides = new HashMap<String, Object>();
for (String envName : env.keySet()) {
  if (envName.contains("JDBC_DATABASE_URL")) {
    configOverrides.put("javax.persistence.jdbc.url", env.get(envName));
  }
}

// provision persistence manager
entityManagerFactory = Persistence.createEntityManagerFactory("defaultPersistenceUnit", configOverrides);
entityManager = entityManagerFactory.createEntityManager();

Perhaps Hibernate isn't picking up the db.default.url?

Upvotes: 0

codefinger
codefinger

Reputation: 10338

Hibernate does not recognize the vendor://user:password@host:port/db format of $DATABASE_URL. It requires a JDBC URL. Try changing your db.default.url to this:

db.default.url=${?JDBC_DATABASE_URL}

For more info see Heroku DevCenter.

Upvotes: 0

Related Questions