La respuesta de James proporciona buenas instrucciones para hacer que Jetty funcione en Heroku, y su comentario incluye un enlace a una buena referencia sobre el uso de Tomcat integrado. Pero también es posible ejecutar la versión estándar e independiente de Tomcat en Heroku. Así es como yo era capaz de conseguir que funcione:
En primer lugar, configurar el POM para instalar y configurar Tomcat como parte de su construcción, y también para implementar la aplicación a la instancia de Tomcat instalada:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat6x</containerId>
<zipUrlInstaller>
<url>http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.zip</url>
</zipUrlInstaller>
<dependencies>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</dependency>
</dependencies>
</container>
<configuration>
<type>standalone</type>
<deployables>
<deployable>
<groupId>com.yourcompany.name</groupId>
<artifactId>yourArtifact</artifactId>
<type>war</type>
<properties>
<context>ROOT</context>
</properties>
</deployable>
</deployables>
</configuration>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>install</goal>
<goal>configure</goal>
<goal>deploy</goal>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
a continuación, crear un archivo de server.xml
recortado hacia abajo que funcionará en Heroku:
<?xml version='1.0' encoding='utf-8'?>
<Server port="-1">
<Listener className="org.apache.catalina.core.JasperListener" />
<Service name="Catalina">
<Connector port="${http.port}" protocol="HTTP/1.1" connectionTimeout="20000"/>
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"/>
</Engine>
</Service>
</Server>
... esto es necesario debido a que su aplicación Heroku sólo se le permite unirse a un solo puerto (que cambia cada vez que una nueva instancia se crea y se especifica en elVariable de entorno). Intentar enlazar a cualquier otro puerto bloqueará su aplicación. Como el puerto es dinámico, se debe pasar al server.xml
a través de la propiedad del sistema http.port
, pero lo abordaremos más adelante.
Mientras estás en ello, también crea un archivo persistence.xml
que trabajará con Heroku:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="quiz_devel">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show.sql" value="true"/>
<property name="hibernate.c3p0.acquire_increment" value="1"/>
<property name="hibernate.c3p0.idle_test_period" value="10"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.max_statements" value="40"/>
<property name="hibernate.c3p0.min_size" value="1"/>
<property name="hibernate.c3p0.timeout" value="30"/>
</properties>
</persistence-unit>
</persistence>
Tenga en cuenta que no hay hibernate.connection.url
especificado aquí. Esto se debe a que Heroku especifica la URL de la base de datos que su aplicación debe usar en la variable de entorno $DATABASE_URL
.
Ahora es el momento para crear un script sencillo que configura el medio ambiente y pone todo de modo que Tomcat en realidad puede funcionar:
#point to the correct configuration and webapp
CATALINA_BASE=`pwd`/target/cargo/configurations/tomcat6x
export CATALINA_BASE
#copy over the Heroku config files
cp ./server-heroku.xml ./target/cargo/configurations/tomcat6x/conf/server.xml
cp ./persistence-heroku.xml ./target/cargo/configurations/tomcat6x/webapps/ROOT/WEB-INF/classes/META-INF/persistence.xml
#make the Tomcat scripts executable
chmod a+x ./target/cargo/installs/apache-tomcat-6.0.18/apache-tomcat-6.0.18/bin/*.sh
#set the correct port and database settings
JAVA_OPTS="$JAVA_OPTS -Dhttp.port=$PORT -Dhibernate.connection.url=$DATABASE_URL"
export JAVA_OPTS
#start Tomcat
./target/cargo/installs/apache-tomcat-6.0.18/apache-tomcat-6.0.18/bin/catalina.sh run
esto está haciendo una serie de cosas:
- Se le dice a Tomcat que use los artefactos de configuración e implementación que cargó el paquete como parte de su compilación, configurando
CATALINE_BASE
para que apunte al lugar correcto.
- Sobrescribe los archivos predeterminados
server.xml
y persistence.xml
con sus variantes específicas de heroku.
- Marca todas las secuencias de comandos de inicio en la instancia de Tomcat que la carga instalada como parte de la construcción como ejecutable.
- Especifica los valores para
http.port
y hibernate.connection.url
en función de las variables de entorno proporcionadas por la plataforma Heroku.
- Finalmente, ejecuta Tomcat. Tenga en cuenta que no puede usar
startup.sh
para hacer esto, ya que startup.sh
lanzará Tomcat en un nuevo proceso y luego finalizará. Heroku no entiende esto, y cree que la terminación de startup.sh
es la finalización del proceso de Tomcat.
Finalmente, el último paso es configurar su Procfile
para llamar a su script de inicio, algo a lo largo de las líneas de:
web: sh startServer-heroku.sh
Con este enfoque puede tener un proyecto que sea compatible con Heroku, a la vez que conserva su capacidad de ejecutar de forma independiente como una aplicación web estándar de Java.
eche un vistazo a [jcabi-heroku-maven-plugin] (http://www.jcabi.com/jcabi-heroku-maven-plugin/index.html), que automatiza todo el proceso de implementación en Heroku. tal vez te ayude en tu caso. – yegor256