Payara Micro in Docker
Originally published on 04 Sep 2017
Last updated on 21 Mar 2019
The Payara Micro 173 release had a few changes which will make the lives of Docker users easier. This blog will cover the changes which affect Payara Micro in Docker, demonstrating the following:
-
Using the new Payara Micro 5 Docker image, which provides Java EE 8 features.
-
Deploying applications without the targetted database being present.
-
Adding library JARs from the command line.
New Payara Server 5 Snapshot Docker images
We have recently begun publishing snapshot builds of Payara Server and Payara Micro 5, our next major version of Payara Server which provides updated APIs such as CDI 2.0. Along with the 173 release of Payara Server, we also began publishing 5-SNAPSHOT tags of our official Docker images which are built daily. These can be used as follows:
- docker run -it payara/micro:5-SNAPSHOT
- docker run -it payara/server-full:5-SNAPSHOT
Adding library JARs from the command line
Payara 5 snapshots also include the latest changes to Payara 173, which means that both the Payara Micro 5 and Payara Micro 173 images have the new --addJars
command option. This option can be used in multiple ways depending on the need. The following usages are supported:
- Adding a single JAR library
e.g.java -jar payara-micro.jar --addJars myLib.jar
- A directory of JAR libraries
e.g.java -jar payara-micro.jar --addJars myLibraryDirectory/
- Adding a colon-separated list of JARs and/or directories (similar to the Java classpath)
e.g.java -jar payara-micro.jar --addJars myLib.jar:myLibraryDirectory/:myOtherLib.jar
- Using
--addJars
in combination with--outputUberJAR
will package all libraries into the JAR so that the long command does not need to be specified each time.
e.g.java -jar payara-micro.jar --addJars myLib.jar --ouputuberjar payara-micro-with-libs.jar
Deploying applications without checking the database
With Payara 173, applications can now be deployed regardless of whether the target database is available. This is extremely useful to users of container-based services since there is no need to start a database inside the container for the application to deploy during the build cycle of the image. This means that the application will be successfully deployed more quickly, more reliably, and the container can start with everything already deployed and configured. Previously, the application may be left undeployed but the container would keep the server running and deem it to be healthy.
Test Project
To demonstrate these features, I have created a test project. The application creates a connection to a database on the server "database" every time /ping
is visited, and returns the validity of the connection. The application contains two short classes and a glassfish-resources.xml
. The full source code for this example is available in our Payara Examples repository, Payara-Examples/Payara-Micro/database-ping.
src/main/webapp/WEB-INF/glassfish-resources.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<!-- Creates a connection pool in Payara to connect to a MySql database called "test" with the server name "database" -->
<jdbc-connection-pool allow-non-component-callers="false"
associate-with-thread="false"
connection-creation-retry-attempts="0"
connection-creation-retry-interval-in-seconds="10"
connection-leak-reclaim="false"
connection-leak-timeout-in-seconds="0"
connection-validation-method="auto-commit"
datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
fail-all-connections="false"
idle-timeout-in-seconds="300"
is-connection-validation-required="false"
is-isolation-level-guaranteed="true"
lazy-connection-association="false"
lazy-connection-enlistment="false"
match-connections="false"
max-connection-usage-count="0"
max-pool-size="32"
max-wait-time-in-millis="60000"
name="jdbc/testConnPool"
non-transactional-connections="false"
pool-resize-quantity="2"
res-type="javax.sql.DataSource"
statement-timeout-in-seconds="-1"
steady-pool-size="8"
validate-atmost-once-period-in-seconds="0"
wrap-jdbc-objects="false">
<property name="URL" value="jdbc:mysql://database:3306/test"/>
<property name="User" value="root"/>
<property name="Password" value="password"/>
</jdbc-connection-pool>
<!-- Creates a DataSource called "jdbc/testDS" for accessing the connection pool -->
<jdbc-resource enabled="true" jndi-name="jdbc/testDS" object-type="user" pool-name="jdbc/testConnPool">
<description>Test DataSource</description>
</jdbc-resource>
</resources>
src/main/java/test/PingEndpoint.java
@Path("/ping")
@RequestScoped
public class PingEndpoint {
// Injects the DataSource called "jdbc/testDS" (it's an app scoped JNDI resource as it was declared in the glassfish-resources.xml).
@Resource(lookup = "java:app/jdbc/testDS")
private DataSource testDS;
/**
* Listens on /ping. Creates a connection, prints the connection validity then closes the connection.
*/
@GET
@Produces(MediaType.TEXT_PLAIN)
public String ping() throws SQLException {
Connection conn = testDS.getConnection();
boolean valid = conn.isValid(3);
conn.close();
return "Connection made.\nChecking validity of connection... " + valid + ".";
}
}
src/main/java/test/RestApplication.java
@ApplicationPath("/")
public class PingEndpoint extends Application {
// Loads each available JAX-RS resource (there's only 1!)
}
The Dockerfile to use this application with Payara Micro is shown below:
# Using the Payara Micro 5 snapshot build.
FROM payara/micro:5-SNAPSHOT
# Downloads the database connector library
RUN wget -O $PAYARA_PATH/database-connector.jar http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.43/mysql-connector-java-5.1.43.jar
# Adds an application to be loaded
ADD myapplication.war $PAYARA_PATH
ENTRYPOINT ["java", "-jar", "$PAYARA_PATH/payara-micro.jar", "--addJars", "$PAYARA_PATH/database-connector.jar", "--deploy", "$PAYARA_PATH/myapplication.war"]
Since the application will be deployed regardless of whether the database is available or not, the images can be started in any order (as long as the Payara Micro image has a link to the database server). This means that these images would work together in a Docker Swarm environment. But just for ease, we can just run the following commands:
docker run -d --name database -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=test mariadb
docker run -d -p 8080:8080 --name payara --link database:database custom-micro
After this you can then go to http://localhost:8080/myapplication/ping
, where you should get the following response:
Connection made.
Checking validity of connection... true
Before 173, you might have gotten the following error (as well as an "--addJars is not a valid command line argument
" error!) in the Payara logs:
RAR5038:Unexpected exception while creating resource for pool { PoolInfo : (name=java:app/jdbc/testConnPool), (applicationName=myapplication) }. Exception : javax.resource.spi.ResourceAllocationException: Connection could not be allocated because: Communications link failure
This is because Payara Server would detect that the required database wasn’t running, and would be unable to create the resource for it. This isn’t the case anymore however.
Related Posts
The Payara Monthly Catch - October 2024
Published on 30 Oct 2024
by Chiara Civardi
0 Comments
Can You Futureproof Your Enterprise Java Apps or Are They Doomed to Fall Behind?
Published on 16 Oct 2024
by Chiara Civardi
0 Comments