REST interface on ActiveMQ Artemis - rest

I'm trying to add REST interface to ActiveMQ Artemis by building .war file with Maven following Artemis REST interface documentation.
After .war file is generated I move it in /opt/artemis/apache-artemis-2.13.0/web/ directory and start ActiveMQ Artemis.
I'm getting next exception when starting ActiveMQ Artemis:
WARN [org.eclipse.jetty.webapp.WebAppContext] Failed startup of context o.e.j.w.WebAppContext#4cb702ce{/artemis-rest,file:///var/lib/test-broker/tmp/jetty-0_0_0_0-8161-artemis-rest_war-_artemis-rest-any-15304647904836420970.dir/webapp/,UNAVAILABLE}{/opt/artemis/apache-artemis-2.13.0/web/artemis-rest.war}: java.lang.RuntimeException: You must install RESTEasy as a Bootstrap Listener and it must be listed before this class
at org.apache.activemq.artemis.rest.integration.RestMessagingBootstrapListener.contextInitialized(RestMessagingBootstrapListener.java:39) [artemis-rest-2.13.0.jar:2.13.0]
Also, getting 503 on HTTP request http://192.168.0.50:8161/artemis-rest/queues/test:
HTTP ERROR 503 Service Unavailable
URI: /artemis-rest/queues/test
STATUS: 503
MESSAGE: Service Unavailable
SERVLET: -
I don't have RESTeasy installed because I can't find out how to, so I've downloaded jar file for RESTeasy jaxrs version 3.13.0.Final and put it in WEB-INF/lib directory and also included dependency for it in pom.xml.
Let me show you my configuration:
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.somebody</groupId>
<artifactId>artemis-rest</artifactId>
<packaging>war</packaging>
<name>My App</name>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.13.0.Final</version>
</dependency>
<dependency>
<groupId>org.apache.activemq.rest</groupId>
<artifactId>artemis-rest</artifactId>
<version>2.13.0</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.apache.activemq.artemis.rest.integration.RestMessagingBootstrapListener</listener-class>
</listener>
<filter>
<filter-name>Rest-Messaging</filter-name>
<filter-class>org.jboss.resteasy.plugins.server.servlet.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>Rest-Messaging</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>rest.messaging.config.file</param-name>
<param-value>file:///WEB-INF/rest-messaging.xml</param-value>
</context-param>
</web-app>
rest-messaging.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<rest-messaging>
<server-in-vm-id>0</server-in-vm-id> <!-- deprecated, use "url" -->
<use-link-headers>false</use-link-headers>
<default-durable-send>false</default-durable-send>
<dups-ok>true</dups-ok>
<topic-push-store-dir>topic-push-store</topic-push-store-dir>
<queue-push-store-dir>queue-push-store</queue-push-store-dir>
<producer-time-to-live>0</producer-time-to-live>
<producer-session-pool-size>10</producer-session-pool-size>
<session-timeout-task-interval>1</session-timeout-task-interval>
<consumer-session-timeout-seconds>300</consumer-session-timeout-seconds>
<consumer-window-size>-1</consumer-window-size> <!-- deprecated, use "url" -->
<url>vm://0</url>
</rest-messaging>
If needed I can also attach broker.xml, jolokia-access.xml and bootstrap.xml files, but they seems OK to me. I found older question about this here, but it didn't help to resolve this.
In case you know some other approaches for adding REST interface to ActiveMQ Artemis please inform me.

Unfortunately the REST documentation for ActiveMQ Artemis hasn't been validated or updated in awhile.
You can get everything you need in the war file and exclude most of what you don't need using this pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.somebody</groupId>
<artifactId>artemis-rest</artifactId>
<packaging>war</packaging>
<name>My App</name>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.activemq.rest</groupId>
<artifactId>artemis-rest</artifactId>
<version>2.13.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.logmanager</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
Be sure to add an in-vm acceptor to your broker.xml, e.g.:
<acceptors>
...
<acceptor name="invm">vm://0</acceptor>
</acceptors>
Also, you can automatically include the REST configuration XML if you structure your project like this:
|-- pom.xml
`-- src
`-- main
`-- webapp
`-- WEB-INF
`-- web.xml
`-- resources
`-- rest.xml
Then you can reference it in your web.xml like this:
<context-param>
<param-name>rest.messaging.config.file</param-name>
<param-value>rest.xml</param-value>
</context-param>
In general I would recommend against using the ActiveMQ Artemis REST interface for 2 main reasons:
Your code will not be portable because the ActiveMQ Artemis REST interface is a custom (i.e. not standardized) interface.
The STOMP protocol is ubiquitous, simple, standarized, and can be used in almost every circumstance and environment where REST might be used.
I recommend you use STOMP in lieu of the ActiveMQ Artemis REST interface.

Related

ActiveMQ Artemis REST Interface configuration

I'm attempting to add ActiveMQ Artemis' REST interface to my Docker container, and for that I have been following the official guide. I generate a artemis-rest.war file and move it into my /opt/artemis/web folder. Now when I navigate to http://localhost:8161/artemis-rest/queues/queue_name, I get a 404. When I try to navigate to other resources listed in the /opt/artemis/web like /console/ or /artemis-plugin/ I get at least some sort of a response.
My folder structure looks like this:
|-- pom.xml
`-- src
`-- main
`-- webapp
`-- WEB-INF
`-- web.xml
`-- resources
`-- rest.xml
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.somebody</groupId>
<artifactId>artemis-rest</artifactId>
<packaging>war</packaging>
<name>ActiveMQ Artemis REST</name>
<version>2.17.0</version>
<dependencies>
<dependency>
<groupId>org.apache.activemq.rest</groupId>
<artifactId>artemis-rest</artifactId>
<version>2.17.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.logmanager</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
rest.xml:
<rest-messaging>
<server-in-vm-id>0</server-in-vm-id> <!-- deprecated, use "url" -->
<use-link-headers>false</use-link-headers>
<default-durable-send>false</default-durable-send>
<dups-ok>true</dups-ok>
<topic-push-store-dir>topic-push-store</topic-push-store-dir>
<queue-push-store-dir>queue-push-store</queue-push-store-dir>
<producer-time-to-live>0</producer-time-to-live>
<producer-session-pool-size>10</producer-session-pool-size>
<session-timeout-task-interval>1</session-timeout-task-interval>
<consumer-session-timeout-seconds>300</consumer-session-timeout-seconds>
<consumer-window-size>-1</consumer-window-size> <!-- deprecated, use "url" -->
<url>vm://0</url>
</rest-messaging>
web.xml:
<web-app>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.apache.activemq.artemis.rest.integration.RestMessagingBootstrapListener</listener-class>
</listener>
<filter>
<filter-name>Rest-Messaging</filter-name>
<filter-class>org.jboss.resteasy.plugins.server.servlet.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>Rest-Messaging</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>rest.messaging.config.file</param-name>
<param-value>rest.xml</param-value>
</context-param>
</web-app>
Have I missed something? Do I need to still need to configure something?
I would have though that that including the .war file would be enough, to at least get an error of some kind.
You need to deploy artemis-rest.war in etc/bootstrap.xml, e.g.:
<web bind="http://localhost:8161" path="web">
...
<app url="artemis-rest" war="artemis-rest.war"/>
</web>
The embedded web server won't automatically deploy artemis-rest.war just because you put it into the web directory.

ActiveMQ Artemis REST integration throwing exception

I am trying to REST interface to the ActiveMQ Artemis 2.13.0 by building integrated REST war file and copying the war file to "apache-artemis-2.13.0\web" and starting service.
To configure I have followed this documentation.
Getting exception
2020-12-07 16:47:11,894 INFO [org.apache.activemq.artemis.core.server] AMQ221013: Using NIO Journal
2020-12-07 16:47:11,933 INFO [org.apache.activemq.artemis.core.server] AMQ221057: Global Max Size is being adjusted to 1/2 of the JVM max size (-Xmx). being defined as 477,364,224
2020-12-07 16:47:11,952 ERROR [org.apache.activemq.artemis.core.server] AMQ224097: Failed to start server: java.util.ServiceConfigurationError: org.apache.activemq.artemis.spi.core.protocol.ProtocolManagerFactory: org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManagerFactory not a subtype
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:590) [java.base:]
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1237)
and
2020-12-07 16:47:12,077 WARN [org.apache.activemq.artemis.rest] AMQ182004: REST configuration parameter consumer-window-size' is deprecated. Use 'url' instead.
2020-12-07 16:47:12,409 WARN [org.eclipse.jetty.webapp.WebAppContext] Failed startup of context o.e.j.w.WebAppContext#6b9c42bd{/artemis-rest-1.0,file:///D:/ABroker2.13.0/tmp/jetty-localhost-8161-artemis-rest-1_0_war-_artemis-rest-1_0-any-9922358792097605704.dir/webapp/,UNAVAILABLE}{D:\apache-artemis-2.13.0-bin\apache-artemis-2.13.0\web\artemis-rest-1.0.war}: java.lang.RuntimeException: ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ219007: Cannot connect to server(s). Tried with all available servers.]
at org.apache.activemq.artemis.rest.integration.RestMessagingBootstrapListener.contextInitialized(RestMessagingBootstrapListener.java:54) [artemis-rest-2.13.0.jar:2.13.0]
I have referred old post regarding the similar issue, but didn't resolve my issue.
My pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.jdanekrh</groupId>
<artifactId>artemis-rest</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.19.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>3.0.19.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.0.19.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>tjws</artifactId>
<version>3.0.19.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-server</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-core-client</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-commons</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq.rest</groupId>
<artifactId>artemis-rest</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</project>
And web.xml:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>rest.messaging.config.file</param-name>
<param-value>rest.xml</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<!-- this commented out section is the only difference from the embedded config -->
<!--<listener>-->
<!--<listener-class>-->
<!--org.apache.activemq.artemis.rest.integration.ActiveMQBootstrapListener-->
<!--</listener-class>-->
<!--</listener>-->
<listener>
<listener-class>
org.apache.activemq.artemis.rest.integration.RestMessagingBootstrapListener
</listener-class>
</listener>
<filter>
<filter-name>Rest-Messaging</filter-name>
<filter-class>
org.jboss.resteasy.plugins.server.servlet.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>Rest-Messaging</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Can some one help me if I am missing anything?
You wrote about setting at web.xml
<param-value>rest.xml</param-value>
Make sure that your integrated REST war file really includes /WEB-IBF/classes/rest.xml
Make sure that it contains setting
<rest-messaging>
...
<url>tcp://localhost:61616</url>
</rest-messaging>
Documentation specifies vm://0 instead, but in my view this does not work or demands some custom (non-default) configuration for emdedded broker.

Issue in running a dynamic web project tomcat "Only a type can be imported. org.hibernate.cfg.Configuration resolves to a package"

I am trying to migrate an old Web project ( jsp /java) on eclipse. Created a new Dynamic web project. Copied all the code in respective folders and converted the project into a Maven project and added all the required dependencies. Resolved all compiled time errors. When I am running the project on tomcat through eclipse getting following errors.
org.apache.jasper.JasperException: Unable to compile class for JSP:
An error occurred at line: [18] in the generated java file: [/home/xxx/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/work/Catalina/localhost/webadmin/org/apache/jsp/login_jsp.java]
Only a type can be imported. org.hibernate.cfg.Configuration resolves to a package
Apr 19, 2019 2:21:03 PM org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet [jsp] threw exception
java.lang.ClassNotFoundException: org.apache.jsp.login_jsp
Issue looks to be something related to configuration only. Tried removing conflicts from pom files , tried at all different paths of hibernate.cfg. used latest possible version of jars in pom
First few lines of web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>webapp</display-name>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>sessionfilter</filter-name>
<filter-class> com.blossom.action.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionfilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<servlet>
<description></description>
<display-name>album_insert</display-name>
<servlet-name>album_insert</servlet-name>
<servlet-class>com.xxx.action.album_insert</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>album_insert</servlet-name>
<url-pattern>/album_insert</url-pattern>
</servlet-mapping>
poi.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>webadmin</groupId>
<artifactId>webadmin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>net.sf.ezmorph</groupId>
<artifactId>ezmorph</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.2.Final</version>
</dependency>
<dependency>
<groupId>com.servlets</groupId>
<artifactId>cos</artifactId>
<version>05Nov2002</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</project>
Build Path
1. Tomcat 9.0
2. EAR Libary
3. JRE (java 8 oracle)
4. Maven dependencies
5. Web app libraries
The program should run without error
Seems there's a version mismatch here, tomcat 9 but catalina 6.0.53.
Catalina dependency needs to be upgraded, something like
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>9.0.19</version>
</dependency>
Looking for catalina 6.0.53 on a maven repository shows a warning
Note: This artifact was moved to:
org.apache.tomcat ยป tomcat-catalina
it was a deployment path issue.
After adding Maven dependencies in Properties->Deployment Assembly -> Add ( Java Build Path Entries) -Maven Dependencies the issue is resolved .

Jersey + Swagger + Swagger-UI + Maven configuration

I am trying swagger for the first time with Jersey and Maven, and I am wondering if I am going down the right path. I have jersey, maven, and swagger working on my local computer. Soon, I want to deploy it to different environments and include swagger-ui.
If I configure my web.xml file to <param-value>http://localhost:8080/api</param-value> then I see that swagger works on my local computer. But will I need to change this address every time I want to deploy my code to different environments (for example going from a Dev environment, to QA environment, to Production environment), and if so how would I go about doing that or is it not possible/not what swagger is meant for?
I want to incorporate swagger-ui with my project. I see online suggestions of downloading the file manually from git and placing it in my project. But what I am wondering is if there is a maven dependency that I can use instead so that I can use maven to get the necessary code to use swagger-ui and configure it to work with jersey. If so what is the dependency and how do I use it to deploy the code through multiple environments?
Please give guidance and links to tutorials if possible seeing as I am new to this technology. Also if I am way off in my thought process of using jersey/swagger/swagger-ui/maven without manually downloading code from git and being able to deploy the code through multiple environments please let me know so I can look for another way to use REST in my application.
Thank you for your help.
pom.xml:
<repositories>
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>
<properties>
<jersey2.version>2.19</jersey2.version>
<jaxrs.version>2.0.1</jaxrs.version>
</properties>
<!-- Dependencies -->
<dependencies>
<!-- JAX-RS -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>${jaxrs.version}</version>
</dependency>
<!-- Jersey 2.19 -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey2.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey2.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey2.version}</version>
</dependency>
<!-- Servlet Library -->
<!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring dependencies -->
<!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.0</version>
</dependency>
</dependencies>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>HelloWorldSpring</display-name>
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
io.swagger.jaxrs.listing,
com.jer.rest
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Jersey2Config</servlet-name>
<servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8080/HealthTracker/rest</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- Other XML Configuration -->
<!-- Load by Spring ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<!-- Spring ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Check out the link https://github.com/swagger-api/swagger-samples/tree/2.0/java
It has excellent examples on how to configure Swagger 3.0 in your project (see java-jersey2-webxml example). For earlier versions check the branches
As far as the ui is concerned, you can download required files or you can just add the below dependency in pom.xml.
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.6.1</version>
</dependency>
It will download necessary ui files. You can copy the downloaded index.html in your project and edit the url.
Here's what I think would answer your questions:
To be able to configure swagger as per different environments, then these are the steps you can follow:
i) Create a Bootstrap class to configure swagger bean (ref: https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5 and Setting the Api Version with Swagger UI)
ii) Set the values in the above bean using values from a properties file, which you can easily configure outside your code in any environment.
Swagger dist consists of html/css/image/js files. It cannot be added as a Maven jar dependency.
Hope this helps!
Here a solution with java doclets (no swagger annotations are required). Use the maven-javadoc-plugin and configure the swagger-doclet as an alternate doclet. With maven profiles it is possible to manage different environments:
<profile>
<id>dev</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>generate-service-docs</id>
<phase>generate-resources</phase>
<configuration>
<doclet>com.carma.swagger.doclet.ServiceDoclet</doclet>
<docletArtifact>
<groupId>com.carma</groupId>
<artifactId>swagger-doclet</artifactId>
<version>1.0.3</version>
</docletArtifact>
<reportOutputDirectory>${project.build.outputDirectory}</reportOutputDirectory>
<useStandardDocletOptions>false</useStandardDocletOptions>
<additionalparam>-apiVersion 1 -docBasePath
https://example.com/apidocs -apiBasePath
https://example.com/api -swaggerUiPath
../../../src/main/resources/swagger-ui/
</additionalparam>
</configuration>
<goals>
<goal>javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
I put the swagger resources directly into my project. So it was easy to customize the css and html.
Or, if you do not want to put swagger into your repository, you could use the frotend-maven-plugin to manage your js/css dependencies (like: swagger-ui) with bower.
I deliver swagger as static resources from the embedded server directly (in my case I used grizzly) :
String apiDocs = Env.getApiDocs();
server.getServerConfiguration().addHttpHandler(
new CLStaticHttpHandler(GrizzlyStarter.class.getClassLoader(), apiDocs), apiDocs);
I was faced with the same problem and created a library that if included into a Jersey project will add swagger 3.0 UI. Please take a look code and blog post The idea is that all swagger UI static content is packaged withing the library and extracted at runtime. In addition, library will take care of creating web context for swagger UI and adjust reference to the openapi.json file. You will need to add 2 properties and this code to your project:
SwaggerContext.addSwaggerServlet(tomcat, context,
ConfigBuilder.builder(ConfigType.TYPE_SAFE)
.build()
.getConfig("swagger"),
EmailApplication.class);
and properties:
swagger.package="com.itzap"
swagger.apiBaseUrl="http://{application url}"
If all other configuration is left at defaults swagger UI can be accessed over this URL:
http://{application base URL}/api/v1/swagger

JAR libraries in WEB-INF/lib not added to classpath during Glassfish deployment

I'm new to Glassfish and Java EE although I've been using Java for a few years. I've inherited a project that stalled and now I need to start development on it again. I'm trying to deploy the web application as-is to see what works and what needs attention. While there is a lot of code to implement various functions, it appears that the first point needing attention is deployment of the application.
The web application I'm trying to deploy is MyServer and is packaged in a WAR archive. A class in MyServer has a reference to a class in MyDatabase which implements an interface (InterfaceOne) from MyInterfaces. The class in MyServer also has a direct reference to InterfaceOne from MyInterfaces. MyServer, MyDatabase and MyInterfaces are all projects in Eclipse and packaged using Maven. The MyServer POM file lists MyDatabase as a dependency and the POM file for MyDatabase lists MyInterfaces as a dependency. The MyServer POM file doesn't list MyInterfaces as an immediate dependency but I don't think that this should cause an issue. Eclipse doesn't show any errors in the MyServer class concerned; Eclipse appears to consider the Maven dependencies to be sufficient to locate all necessary classes.
When I deploy the MyServer WAR on Glassfish v3.1.2 via the Admin web console and then view the logs in ~glassfish3/glassfish/domains/MyDomain/logs/server.log I encounter the following errors:
[#|2014-05-29T10:06:02.371+0100|SEVERE|glassfish3.1.2|global|_ThreadID=80;_ThreadName=Thread-2;| Class [ my/interfaces/InterfaceOne] not found. Error while loading [ class my.server.ControllerOne ]|#]
[#|2014-05-29T10:06:02.387+0100|SEVERE|glassfish3.1.2|global|_ThreadID=80;_ThreadName=Thread-2;|Class [ my/interfaces/InterfaceOne ] not found. Error while loading [ class my.server.ControllerOne ]|#]
There are two errors shown relating to the interface while trying to load the class from MyServer. If I remove either the reference to MyDatabase or the direct reference to InterfaceOne from MyInterfaces from the my.server.ControllerOne class then one of the errors above disappears (which is expected and just confirms that the error is related to the references (directly and indirectly) of the InterfaceOne from MyInterfaces.
Similar questions including here, here and here all mention ensuring that the required libraries (my-database.jar and my-interfaces.jar) are located in the WEB-INT/lib directory of the MyServer application's WAR archive. However, if I inspect the generated WAR archive for MyServer then the libraries are indeed located in the WEB-INF/lib/ directory. If I inspect the ~glassfish3/glassfish/domains/MyDomain/applications/MyServer/WEB-INF/lib/ directory after deployment the libraries are there too. I assume this indicates that they were successfully extracted from the WAR archive and placed on the Glassfish server. The point is the libraries are definitely there!
All I can think of is that the libraries are not added to classpath of the JVM trying to load the classes of MyServer but surely if Glassfish tries to load classes of an application then it should also first load the libraries packaged with the application shouldn't it? Indeed this page from the Oracle GlassFish Server Application Development Guide
Release 3.1.2 indicates that the WEB-INF/lib/ directory of an application is added to the application's classpath.
I've seen other suggestions that libraries required by web applications be placed in the ~glassfish3/glassfish/domains/MyDomain/lib/ext/ directory. That might very well work but my specific libraries are required by the MyServer application only, not the whole of MyDomain. As far as I can tell, it should be valid to place them in the WEB-INF/lib/ directory of my application.
Does anyone have any ideas about why the my-database.jar and my-interfaces.jar libraries don't seem to be added to the classpath during deployment? More specifically, does anyone know why the my.interfaces.InterfaceOne class isn't visible while loading the my.server.ControllerOne class during deployment?
MyServer's web.xml content:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>MyServer</display-name>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
<welcome-file>default.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/balusc.taglib.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
</web-app>
MyServer pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.webapp</groupId>
<artifactId>my-server</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>My Server</name>
<parent>
<groupId>my.webapp</groupId>
<artifactId>my-parent-pom</artifactId>
<version>1.5</version>
</parent>
<organization>
<name>Example</name>
<url>http://www.example.com</url>
</organization>
<repositories>
<repository>
<id>eclipselink</id>
<url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>eclipselink</groupId>
<artifactId>eclipselink</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>utilities</groupId>
<artifactId>utilities</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>my.webapp</groupId>
<artifactId>my-database</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<!-- <configuration> section added to pick up the WEB-INF/web.xml inside
WebContent -->
<configuration>
<webResources>
<resource>
<directory>WebContent</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
<scm>
<connection>scm:svn:https://svn.server/location/in/repo/my_server</connection>
<developerConnection>scm:svn:https://svn.server/location/in/repo/my_server/trunk</developerConnection>
</scm>
</project>
MyDatabase pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>my-database</artifactId>
<version>0.1.0-SNAPSHOT</version>
<parent>
<groupId>my.webapp</groupId>
<artifactId>my-parent-pom</artifactId>
<version>1.5</version>
</parent>
<dependencies>
<dependency>
<groupId>eclipselink</groupId>
<artifactId>eclipselink</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>bcrypt</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>my.webapp</groupId>
<artifactId>my-interfaces</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jpa_3.0_spec</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<scm>
<connection>scm:svn:https://svn.server/location/in/repo/my_database</connection>
<developerConnection>scm:svn:https://svn.server/location/in/repo/my_database/trunk/</developerConnection>
</scm>
<groupId>my.webapp</groupId>
</project>
MyInterfaces pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my.webapp</groupId>
<artifactId>my-interfaces</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>my.webapp</groupId>
<artifactId>my-parent-pom</artifactId>
<version>1.5</version>
</parent>
<scm>
<connection>scm:svn:https://svn.server/location/in/repo/my_interfaces</connection>
<developerConnection>scm:svn:https://svn.server/location/in/repo/my_interfaces/trunk</developerConnection>
</scm>
<dependencies>
<dependency>
<groupId>my.webapp</groupId>
<artifactId>my-utilities</artifactId>
<version>0.1.2</version>
<classifier>me</classifier>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The MyInterfaces POM lists a dependency on MyUtilities. I think this can be safely ignored for this question since none of it's classes appear in the error messages I've described. It is also placed in the WEB-INT/lib/ directory on the Glassfish server when my application is deployed.
(Glassfish questions appear to require a lot of info like web.xml files and pom.xml etc. Thanks for taking the time to sift through all of this.)
I have set up a project with basically the same structure as you described and I can't reproduce the problem nor do I have an additional idea what could be wrong.
Therefore I have pushed my test project to GitHub so you can try it and maybe you find any hint what is different in your project.
The project is here: https://github.com/erdbeerschnitzel/war-packaging
If you don't have a GitHub account to clone the project you can download the ZIP (button on the lower right). Extract it somewhere and load the 5 projects in your IDE, build everything and deploy the WAR file of the my-server project.
I left out the parent project and removed some dependencies like eclipselink and primefaces but I think that shouldn't make the difference.
Good luck.
Update:
Glassfish has separate Deploy and Launch actions. I'd expect Deploy to
upload, extract the WAR and register anything that needs to be
registered. I'd expect the Launch action to actually load classes and
start processes. Why are classes being loaded when I deploy?
Actually the application (and therefore the classes) is loaded when you deploy it.
It appears that there were two issues at play:
Firstly MyServer's web.xml <display-name> was incorrect. This
wasn't visible in my question because I'd changed the library names
(which contain client names). Part of the requirements given to me
for the project were to rebrand the project and I missed the
<display-name> element. Oops.
The second issue was that, while
investigating this issue, I moved the MyDatabase and
MyInterfaces libraries from the MyServer WEB-INF/lib/
directory to the domain's lib/ext/ directory and back. This
changed the errors logged during deployment (since the libraries
were visible despite the incorrect <display-name> but they errors
didn't reappear when I moved the database and interface libraries
back into the MyServer application. I think Glassfish was caching
the libraries and not updating the cached libraries during
deployment. Stopping/starting the domain updated the cache.
To summarise, once the <display-name> of MyServer was changed and the Glassfish library cache was updated, the class loading errors appear resolved.