
Leading the Way: Payara Platform Community 7 Beta Now Fully Jakarta EE 11 Certified
We’re excited to announce that Payara Platform Community 7 Beta application server is now fully certified as Jakarta EE 11 […]
Payara Micro provides build tool plugins for Maven and Gradle. The plugins allows to start/stop/reload Payara Micro instance and package uber jar bundle of application. To illustrate the use of Payara Micro Maven Plugin, I’ll be revisiting my earlier blog on another feature of Payara Micro – the ability to use Payara Micro as a JMS consumer.
I’ll gradually modify the example from that blog post to make full use of the plugin. Full reference documentation for the plugin is available in ourdocumentation GitBook.
Bundle the ActiveMQ RAR into an Uber JAR
The first improvement we can make is to use the payara-micro:bundle
goal to create an Uber JAR containing the ActiveMQ resource adapter. This will let us specify the Maven GAV coordinates of the ActiveMQ RAR so we don’t have to bother downloading the artefact ourselves.
<plugin>
<groupId>fish.payara.maven.plugins</groupId>
<artifactId>payara-micro-maven-plugin</artifactId>
<version>1.0.7</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<payaraVersion>5.201</payaraVersion>
<deployArtifacts>
<artifactItem>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-rar</artifactId>
<version>5.15.12</version>
<type>rar</type>
</artifactItem>
</deployArtifacts>
</configuration>
</plugin>
I’ve separated out the configuration properties I’ve set above.
<payaraVersion>
<deployArtifacts>
This property allows you to add a list of <artifactItem>
, which are just Maven GAV coordinates of applications to be deployed on the Payara Micro instance.
2. Deploy the built JMS11NotificationConsumer app
Our next step is to deploy the JMS11NotificationConsumer app using the payara-micro:start
goal:
<plugin>
<groupId>fish.payara.maven.plugins</groupId>
<artifactId>payara-micro-maven-plugin</artifactId>
<version>1.0.7</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
<goal>start</goal>
</goals>
</execution>
</executions>
<configuration>
<payaraVersion>5.201</payaraVersion>
<deployArtifacts>
<artifactItem>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-rar</artifactId>
<version>5.15.12</version>
<type>rar</type>
</artifactItem>
</deployArtifacts>
<useUberJar>true</useUberJar>
<commandLineOptions>
<option>
<key>--deploy</key>
<value>target/jms11-notification-consumer-1.0-SNAPSHOT.jar</value>
</option>
<option>
<value>--autobindhttp</value>
</option>
</commandLineOptions>
</configuration>
</plugin>
Here, I have made a couple of additions to my plugin configuration. I have added the start
goal, and some configuration options for that goal:
<useUberJar>true
</useUberJar>
The default behaviour is not to use the bundled Uber JAR. Setting this property to true means that Maven will attempt to start the Uber JAR, rather than look for a path to an executable specified with <payaraMicroAbsolutePath>
.
<commandLineOptions>
This property allows you to declare all the same command line options as are available when launching a Payara Micro instance from the terminal. Each <option>
must be specified as its own key/value pair. Do be aware that the <value>
property must always have a value.
Why didn’t we just add another artifact to the <deployArtifacts>
list of the payara-micro:bundle
goal?
The <deployArtifacts>
list would have allowed us to bundle both the RAR and our application at once in an Uber JAR; meaning that everything is packaged in a single unit. The problem is that our JMS11NotificationConsumer application depends on the ActiveMQ RAR, so the RAR must be deployed first. When we package everything into the Uber JAR, we lose any concept of deployment order, so the application might try to deploy before the ActiveMQ RAR and fail when the Payara Micro instance is started.
This method does actually have some benefits when using a Docker container. Keeping a skinny WAR or JAR containing business logic separate means that there can be a significant benefit from Docker’s layering system. The ActiveMQ RAR version will change far less frequently than our app and is where the majority of the disk space is taken up. Since Docker only builds the layers which change, this is likely to mean rebuilding (and pushing to a registry!) a few KB rather than a few MB.
Why didn’t we use the <deployWar>
property of the payara-micro:start
goal?
The reason we didn’t use this is for the simple fact that we are creating an EJB JAR, not a WAR file, so this property would not have deployed our app. If the resulting artifact was a WAR, then this property would have worked with our configuration.
3. Refactor the application to avoid using a post-deploy command file
We could have simply reused the existing post-deploy.asadmin file from the previous blog and supplied that with another <option>
but, since that configuration can be done via annotations, it means we can include that configuration in the app and avoid having to maintain multiple files.
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/notifierQueue"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "notifierQueue"),
@ActivationConfigProperty(propertyName = "resourceAdapter", propertyValue = "activemq-rar-5.15.12")
})
@ConnectionFactoryDefinition(name = "java:global/jms/myConnectionPool",
interfaceName = "javax.jms.ConnectionFactory",
resourceAdapter = "activemq-rar-5.15.12",
properties = {"UserName=admin", "Password=admin", "ServerUrl=tcp://127.0.0.1:61616"
})
@AdministeredObjectDefinition(resourceAdapter = "activemq-rar-5.15.12",
interfaceName = "javax.jms.Queue",
className = "org.apache.activemq.command.ActiveMQQueue",
name = "java:global/jms/notifierQueue",
properties = {"PhysicalName=notifierQueue"
})
public class JMS11NotificationConsumer implements MessageListener {
...
Here, I have added the @ConnectionFactoryDefinition
and created the notifierQueue with an @AdministeredObjectDefinition
annotation. The values of these properties are the same as I used in my previous blog.
4. Start Payara Server with the JMS notifier enabled
Finally, we need to start Payara Server with the healthcheck service pushing data through it the JMS notifier. This is covered in steps 5-7 in my previous blog but, to summarise, the asadmin commands to run against Payara Server are as follows:
asadmin deploy activemq-rar-5.15.12.rar
asadmin set resources.connector-connection-pool.jms/__defaultConnectionFactory-Connection-Pool.resource-adapter-name=activemq-rar-5.15.12
asadmin notification-jms-configure --password=admin --connectionFactoryName=jms/__defaultConnectionFactory --queueName=notifierQueue --contextFactoryClass=com.sun.enterprise.naming.SerialInitContextFactory --dynamic=true --enabled=true --url=localhost:61616 --username=admin --target=server-config
asadmin healthcheck-service-configure-checker-with-thresholds --thresholdWarning=50 --unit=MILLISECONDS --thresholdCritical=80 --checkerName=CPUC --dynamic=true --time=5000 --serviceName=healthcheck-cpu --thresholdGood=0 --enabled=true --target=server-config
asadmin healthcheck-configure --historicalTraceEnabled=false --notifierEnabled=true --dynamic=true --enabled=true --historicalTraceStoreSize=20 --target=server-config
We should now see the same results as we saw before but, now we have set up our Payara Micro environment with the plugin configuration, we have less work to do each time we want to see a change.
We can simply run the goals mvn clean install payara-micro:bundle payara-micro:start
and that should be enough!
There are lots of other features in the plugin which aren’t covered in this blog post – a complete reference is available in our documentation. The biggest advantage to using this plugin is in creating an Uber JAR. Previously, users needed to use the Maven Exec plugin to call the --outputUberJar
option on a previously downloaded Payara Micro JAR. This meant that Payara Micro would need to start to create the Uber JAR, and then start again when actually running the created Uber JAR. Now, the bundle goal takes care of that, and Payara Micro does not need to start, meaning a big chunk of build time is eliminated.
There are lots of different ways you may choose to use this plugin and many ways to achieve the same goal, so there’s sure to be something to fit your workflow!
{{cta(‘0c1037e0-adaf-4401-b888-05088602db6a’)}}
We’re excited to announce that Payara Platform Community 7 Beta application server is now fully certified as Jakarta EE 11 […]
Managing Payara Server Just Got Smarter Imagine managing your Jakarta EE applications not just with Maven goals, but by […]
Welcome aboard the August 2025 issue of The Payara Monthly Catch! With summer in full swing, things may have felt […]
that’s great, but, I see that you’ve configured the activemq connection as using localhost, and put it directly into the annoation on the source code. shouldn’t this be deferring to a jndi configuration property so that it will be changeable in the container without requiring a code rebuild to deploy in a different environment? unless you are expecting the same machine that’s hosting payara is also hosting an activemq instance?
Hi Peter,
This is a demo of the capabilities of the Payara Micro Maven plugin. JNDI configuration is certainly a good option, as is using the new Config API being released with 173. That’s not what this post is about, though, so it makes sense to keep everything else simple.
Mike
Hey,
Maybe someone can help me with a quick problem. I’m trying to build a UberJar with the Maven Plugin. Everything seems to work just fine and I can see the output jar. But when I try to execute the jar
java -jar uber-jar.jar
I get the following error:
Exception in thread “main” java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at fish.payara.micro.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at fish.payara.micro.boot.loader.Launcher.launch(Launcher.java:107)
at fish.payara.micro.boot.loader.Launcher.launch(Launcher.java:70)
at fish.payara.micro.boot.PayaraMicroLauncher.main(PayaraMicroLauncher.java:72)
at fish.payara.micro.PayaraMicro.main(PayaraMicro.java:358)
Caused by: java.lang.IllegalArgumentException: Malformed uxxxx encoding.
at java.util.Properties.loadConvert(Unknown Source)
at java.util.Properties.load0(Unknown Source)
at java.util.Properties.load(Unknown Source)
at fish.payara.micro.impl.PayaraMicroImpl.setBootProperties(PayaraMicroImpl.java:2193)
at fish.payara.micro.impl.PayaraMicroImpl.(PayaraMicroImpl.java:1057)
at fish.payara.micro.impl.PayaraMicroImpl.getInstance(PayaraMicroImpl.java:235)
at fish.payara.micro.impl.PayaraMicroImpl.getInstance(PayaraMicroImpl.java:212)
at fish.payara.micro.impl.PayaraMicroImpl.main(PayaraMicroImpl.java:196)
… 9 more
Any ideas on how I can solve this?
Thanks in advance,
Val
Hi,
This is because the boot.properties file in the JAR is corrupted. Please raise an issue on https://github.com/payara/Payara/issues/ and post the content of the file “MICRO-INF/payara-boot.properties” inside the generated JAR.
It’s possible that you run on Windows and that there are encoding problems with some characters.
As a workaround, I would try building the uber JAR from the command line with java -jar payara-micro.jar –outputuberjar uber.jar and try if it works. The maven plugin uses a different way of creating the uber jar and it may cause problems. If the uber JAR created from command line works, then you can use the maven exec plugin to build the uber jar this way instead of the payara maven plugin.