I've tried many different ways to make the resteasy client work for me, but I'm stuck on an error.
java.lang.LinkageError: Failed to link org/jboss/resteasy/client/jaxrs/internal/ClientConfiguration
Here is the method I'm using as a client
public void createIssue() {
issue = new Issue();
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("api-being-posted-to");
Response response = target.request().header("Authorization: ", "Basic Foo")
.post(Entity.entity(issueJson, "application/json"));
}
I can POST and GET with the same data this is using, and I've tried making a client work with different data and posting to different places and always get the same error. Here's my pom:
<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>org.foo.bar</groupId>
<artifactId>foo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>example</name>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.1.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>3.0.8.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.1.0.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
</plugin>
</plugins>
</build>
and here's my 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">
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>
I'm using JBoss EAP 6.4 if that helps.
As far as I can tell the provided version of resteasy in JBoss EAP 6.4 is 3.0.21.Final and not 3.1.0.Final but you might have modified that (see https://developer.jboss.org/thread/262213 for reference).
You use different versions and different scopes for your resteasy libraries (3.0.8.Final for jaxrs-api) but that might still be ok.
I would always recommend to use the Resteasy Proxy Framework. It might be a bit more code to write but makes things easier and clearer in total:
Define an Interface:
public interface IssueIF
{
#POST
#Path("/issue")
#Produces("text/plain")
Issue postIssue(Issue i);
}
Use it:
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target("http://example.com/base/uri");
SimpleClient simple = target.proxy(IssueIF.class);
Issue issue = new Issue();
client.postIssue(issue);
I did not compile this code, it is mostly copy/pasted from the docs but it should be close to what you need.
Edit:
From the docs:
Subclasses of LinkageError indicate that a class has some dependency
on another class; however, the latter class has incompatibly changed
after the compilation of the former class.
This suggest that you have a problem with different library versions you use for compilation and on runtime so see above at no 1.
Especially if you use different scopes it is essential that the versions are the same for compilation and runtime! So try to find out which versions your JBoss supplies and only use these versions. Also find out which of your referenced libraries are supplied and mark all of them with scope provided.
Related
I have actually a similar problem as described here JAX-RS Resource not found in GlassFish Server. Since one should not ask for help in the answers I make a new question.
I created a project named "SPCore" which is a simple RESTful Webservice. It uses jax-rs libs, jdk 11 and a Tomcat 9.0.44 server. I have an index.html in the webapps folder which shows Hello World. The context path is set to /sp-core. If I'm calling localhost:8080/sp-core the index.html file is returned. So that works.
I have some resources (I will only show one as example). The resource "ProcessEventResource" should return "hello world" as plain text when a GET request comes. The path is set to #Path("processEvent"). Sadly I get an error 404 when I'm calling localhost:8080/sp-core/processEvent
I tried so far:
add an / at the beginning of the path declaration
I added a subclass application as mentioned here in the updated answer JAX-RS Resource not found in GlassFish Server. Still I get the 404 error when calling localhost:8080/sp-core/api/rest/processEvent
I have the assumption that something with the servlets or paths is not working correctly.
In the following I will provide my project structure, the pom file, the resource and the application class. I cut some small parts (package names, group-id, ...) which refers to the company I'm working for. If you need more Information please let me know.
Project structure
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>
<artifactId>sp-core</artifactId>
<version>1.0-SNAPSHOT</version>
<name>sp-core</name>
<packaging>war</packaging>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.0</version>
</plugin>
</plugins>
</build>
processEventResource which simply returns hello world:
#Path("processEvent")
#Provider
public class ProcessEventResource {
public ProcessEventResource(){
}
#GET
#Produces("text/plain")
public String processEvent() {
return "Hello, World!";
}
}
RestApplication class:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api/rest")
public class RestApplication extends Application {
}
I would expect to get the hello world response when I'm calling localhost:8080/sp-core/api/rest/processEvent
Thanks in advance for your help and time.
+++++++++++++++++++++++++++Update+++++++++++++++++++++++++++
I switched from dependency javax to jersey and added a web.xml file. The new pom.xml looks like this
<name>sp-core</name>
<packaging>war</packaging>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.33</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.33</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.33</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.0</version>
</plugin>
</plugins>
</build>
The web.xml looks like this:
<display-name>sp-core</display-name>
<servlet>
<servlet-name>RestServlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Now I either get a 404 with message "Not Found" or "The requested resource [/sp-core/api/rest/processEvent] is not available". Which path should go where so I get the return "Hello World" when I call localhost:8080/sp-core/api/rest/processEvent
+++++++++++++++++++++++++++Update+++++++++++++++++++++++++++
I added init parameter to the web.xml
<init-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>abc.de.fg.SPCore.RestApplication</param-value>
</init-param>
The error message is still the same.
After reading many stackoverflow questions, JAX-RS docu and in the end maven docu I finally got it done. So I will show what I have done in the end.
As I wrote in the first update I added a web.xml file which ended up looking like this.
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>sp-core</display-name>
<servlet>
<servlet-name>restServlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>abc.de.fg.sp_core.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restServlet</servlet-name>
<url-pattern>/api/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Please note, that the param name for the application is javax.ws.rs.Application and not javax.ws.rs.core.Application as said in the documentation (always read the notes ...).
I ended up only using the jersey container-servlet and the jersey-hk2 dependencies (JSON dependency is only for another resource). So the pom.xml looks like the following:
<?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>abc.de.fg</groupId>
<artifactId>sp-core</artifactId>
<version>1.0-SNAPSHOT</version>
<name>sp-core</name>
<packaging>war</packaging>
<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.33</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.33</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.0</version>
</plugin>
</plugins>
</build>
</project>
My RestApplication overrides the getClasses Method from the Application class. There I added all my resources. The ApplicationPath is set to /*
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
#ApplicationPath("/*")
public class RestApplication extends Application {
public RestApplication() {
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(ProcessEventResource.class);
return s;
}
}
And then it finally worked and I got my Hello World when requesting http://localhost:8080/sp-core/api/rest/processEvent.
Another short problem I run into was a 500 error missing RestApplication class. Simply forgot to maven compile ...
Hope this question and answer helps others.
Cheers :)
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
Condition
1.resteasy 3.0.4.Final
2.eclipse
3.maven
Action
I got war package into tomcat7(window x64) webapps and server run normally.
Visit http://localhost:8080/test-resteasy/rest/message/hello, and browser print "Restful example : hello".
But when I maven build tomcat7:run tomcat7-maven-plugin in eclipse,visit the same url throws:
javax.ws.rs.NotFoundException: Could not find resource for full path
Source (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 version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<!-- Auto scan REST service -->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<!-- this need same with resteasy servlet url-pattern -->
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
(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>top.crowley.rest</groupId>
<artifactId>resteasy</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>resteasy Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>3.0.4.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.4.Final</version>
</dependency>
</dependencies>
<build>
<finalName>test-resteasy</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8080</port>
<path>/test-resteasy</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>test resteasy</finalName>
<server>tomcat7</server>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
MessageRestService
package top.crowley.resteasy;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
#Path("/message")
public class MessageRestService {
#GET
#Path("/{param}")
public Response printMessage(#PathParam("param") String msg) {
String result = "Restful example : " + msg;
return Response.status(200).entity(result).build();
}
}
Conjecture
I think of source code is correct, because of run war package in single tomcat 7 server successful. Maybe lack of some dependencies in pom.xml.
Thanks!
Really long post to analyze each POM dependency....but why don't you give a try to compile maven in this way, suggested by official resteasy team?
mvn clean install
mvn jetty:run
https://github.com/resteasy/resteasy-examples/tree/3.1.1.Final/resteasy-springMVC
I'm following this guide to build my hello world web service and get kind of stuck, here are my codes:
MyResource.java:
package com.example;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("myresource")
public class MyResource {
#GET
#Produces("text/plain")
public String getIt() {
return "Got it!";
}
}
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>ts</groupId>
<artifactId>mtest</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>mtest Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.19</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-servlet</artifactId>
<version>2.19</version>
</dependency>
</dependencies>
<build>
<finalName>mtest</finalName>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.0.M1</version>
</plugin>
</plugins>
</build>
web.xml:
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Servlet declaration can be omitted in which case
it would be automatically added by Jersey -->
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/myresource/*</url-pattern>
</servlet-mapping>
Now my problems are:
After launching Jetty, I can get a hello world of my jsp from http://localhost:8080/, but http://localhost:8080/myresource returns 404
Intellij complains Element web-app must be declared
Add your servlet declaration in the web.xml like this
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
that should work. And sometimes the path needs a bar like this.
#Path("/myresource")
And see that, if you put
<url-pattern>/myresource/*</url-pattern>
you have to hit
http://localhost:8080/myresource/myresource
one by your web configuration, and another by the path of your resource.
but, if you are trying this in tomcat, you need to include the artifactId too, like this:
http://localhost:8080/mtest/myresource/myresource
I hope that this help you.
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.