I'm looking at every way to try to make a request type to get to my web service created by restfull Webservice into a project with Tomcat , Maven and some servlets , but nothing I do not start by mistake does not find the resource . What am I doing wrong? I may not have configured the web.xml ? how can I do?
I put the file pom.xml below and
<dependencies>
<dependency>
<groupId>org.glassfish.metro</groupId>
<artifactId>webservices-rt</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.3</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20150729</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
</dependencies>
This is code of my web service:
#Path("ws")
public class WsUserJson {
#Context
private UriInfo context;
/**
* Creates a new instance of WsUserJson
*/
public WsUserJson() {
}
/**
* Retrieves representation of an instance of com.lillonet.testmavenservletws.WsUserJson
* #return an instance of java.lang.String
*/
#GET
#Produces("application/json")
public String getJson(#QueryParam("name") String nome) {
//TODO return proper representation object
return "{"+nome+"}";
}
/**
* PUT method for updating or creating an instance of WsUserJson
* #param content representation for the resource
* #return an HTTP response with content of the updated or created resource.
*/
#PUT
#Consumes("application/json")
public void putJson(String content) {
}
}
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
That is only a jar with a bunch of interfaces. There is no implementation. That dependency should only be used when you plan on deploying to a an EE compliant Server, like Glassfish or Wildfly. Tomcat is not an EE compliant server. It is only a Servlet container. Therefore any features you use from that javaee-web-api, you need to also include an implementation.
So for now, just get rid of it so you don't use ant classes for which there is no implementation. Then you need to decide on a JAX-RS implementation to use. For now I'll just say to use Jersey. So just add this dependency
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.22.1</version>
</dependency>
Then you need to configure the application in the web.xml. You can see here for more options. You basically want something like
<web-app>
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.foo.myresources</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
The param-value in the init-param is the package you want Jersey to scan to pick up and register all your classes annotated with #Path and #Provider. The scan is recursive, so you can list the root-most package in your project if you have your resource scattered in different packages.
From here it should work. Then for JSON/POJO support, you can just add the following dependency
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.1</version>
</dependency>
No extra configuration is needed for that.
Related
i'm trying to make a simple rest service and deploy the app on wildfly server and when i try to deploy my app on server i have the following exception:
Cannot upload deployment: {"WFLYCTL0080: Failed services" =>
{"jboss.undertow.deployment.default-server.default-host./resttestapp" =>
"org.jboss.msc.service.StartException in service
jboss.undertow.deployment.default-server.default-host./resttestapp:
com.sun.jersey.api.container.ContainerException: The ResourceConfig
instance does not contain any root resource classes. Caused by:
com.sun.jersey.api.container.ContainerException: The ResourceConfig
instance does not contain any root resource classes."}}
I've tried a lot of thing from stackoverflow but nothing works for me.
I'm using Wildfly 9.0.2 (standalone, deploying via admin console), Intellij idea.
This is part of my pom.xml:
<groupId>cz.prg.rob</groupId>
<artifactId>resttestapp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>resttestapp Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<jersey.version>1.19.4</jersey.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://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>
<!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-core -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-server -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-bundle -->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
</dependencies>
This is my web.xml:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>JerseyServlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>cz.prg.rob</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JerseyServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
This is my service class:
package cz.prg.rob;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import java.util.Date;
#Path("/name")
public class UserService {
#GET
#Produces("text/plain")
public String getName() {
return "Qwerty";
}
#GET
#Path("/user")
#Produces("application/json")
public User getUser(#QueryParam("name") String name, #QueryParam("surname") String surname, #QueryParam("birthDate") Date birthDate) {
return new User(name, surname, birthDate);
}
}
and this is a part of my User (model) class:
#NoArgsConstructor
#AllArgsConstructor
#Data
public class User {
private String name;
private String surname;
private Date birthDate;
}
This is my project structure:
I can't understand what i'm doing wrong. Please help me.
The solution that helped me:
I've added this as init param of JerseyServlet
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>cz.prg.rob.UserServiceApplication</param-value>
</init-param>
And this is the class where i've defined my resource class
public class UserServiceApplication extends Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(UserService.class);
return s;
}
}
So looks like i have to say to jersey which classes are resource classes explicitly. If you want to add new resource classes just add them in HashSet into getClasses() method.
I have this problem. I'm trying to use Jersey 2.x in order to make REST api, and I would like to use jsp pages for my template (everything without spring or springboot, I can't include them into my project). I have a maven project with this structure:
enter image description here
the pom.xml has the following dependencies:
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-jsp</artifactId>
<version>2.27</version>
</dependency>
</dependencies>
and the web.xml is:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>testjsp</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>it.testjsp.config.JerseyConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>testjsp</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
When I run my app with tomcat, the following url
http://localhost/testjsp
redirects correctly the index.hml.
I have configured the JerseyConfig class in the following way:
#ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("it.testjsp.endpoints");
register(JspMvcFeature.class);
property("jersey.config.server.mvc.templateBasePath", "/WEB-INF/jsp");
}
}
In order to map all the end points exposed into that package and to use jsp pages into WEB-INF/JSP.
I have two end points:
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public class TestEndPoint {
#GET
public Map<String, Object> testApi() {
System.out.println("test jersey 2.27");
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", "test jersey 2.27");
return result;
}
}
This is inside TestEndPoint class and the application responds as I expect (http://localhost/testjsp/api/test returns the json).
The PagesEndPoint is:
#Path("/pages")
public class PagesEndPoint {
#GET
#Path("{pageName}")
public Viewable getPage(#PathParam("pageName") String pageName) {
System.out.println("Try " + pageName + ".html");
return new Viewable("/" + pageName + ".html");
}
}
But when I run the app with tomcat, I have always a 404. Is possible to use jsp (or other html pages)? What I did wrong? Thanks for the help
here is my web.xml
<servlet>
<servlet-name>Learn</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Learn</servlet-name>
<url-pattern>/learn/*</url-pattern>
</servlet-mapping>
if i change this code
<url-pattern>/learn/*</url-pattern>
to
<url-pattern>/learn/abc/</url-pattern>
i can hit my controller code which is given as
#Controller
#RequestMapping(value = "/learn")
public class ControllerClass
{
#RequestMapping(value = "/", method = RequestMethod.GET)
public String callRequest(ModelMap model)
{
return "index";
}
#RequestMapping(value = "/abc/", method = RequestMethod.GET)
public String personController(ModelMap model)
{
return "welcome";
}
}
but i also want to hit the first method or i will add more method, which i can not achieve by
/learn/abc/
in url mapping.
so please help me out with this
pom.xml
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- spring-context which provides core functionality -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- The spring-aop module provides an AOP Alliance-compliant aspect-oriented
programming implementation allowing you to define -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- The spring-webmvc module (also known as the Web-Servlet module) contains
Spring’s model-view-controller (MVC) and REST Web Services implementation
for web applications -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- The spring-web module provides basic web-oriented integration features
such as multipart file upload functionality and the initialization of the
IoC container using Servlet listeners and a web-oriented application context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
</dependencies>
please let me know if i missed any dependency
With this url-pattern <url-pattern>/learn/*</url-pattern> configuration, to hit your method, the url path will be: /learn/learn
The url-pattern atribute on the web.xml works like a basepath for spring's servlet. So a good option is to change your url-pattern to /* , like this:
<url-pattern>/*</url-pattern>
Or if you want some basepath, change the url pattern to something like this:
/basepath/*
And to hit your method, you need to use the path url: /basepath/learn
I have a problem integrating Drools with Spring. I am trying to make a simple Hello World spring example, I reached a moment where my simple project refuses to compile.
To work with Drools annotations like #KSession I need the drools-spring package, but it seems incompatible with Spring 3. As builder I use Maven. Here is how my .pom's looks like:
<dependencies>
<!-- Drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>6.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-spring</artifactId>
<version>6.0.0.Beta2</version>
</dependency>
<!-- Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
</dependencies>
I use very simple case of controller class:
#Controller
#RequestMapping(value = "/")
public class BaseController extends AbstractController {
private static final Logger log = Logger.getLogger(BaseController.class);
#Autowired
#KSession("ksession-rules")
KieSession mySession;
#RequestMapping(value = "/test")
public #ResponseBody
String test() {
Fact myFact = new Fact();
myFact.setFactNumber(20); //According to my rule when myFact.number>20
//then result will be set to "Hello World"
mySession.insert(myFact);
mySession.fireAllRules();
return myFact.getResult();
}
}
At this point I receive an error:
"The hierarchy of the type BaseController is inconsistent".
I noticed that if I remove drools-spring from the dependency list the project compiles successfully. However without that package I cannot deploy my project, because the deployer demands the drools' class responsible for interpreting #KSession and that class is located in drools-spring package.
After some investigation it appears that my Drools session configuration seems to have
nothing to do with the error above, so for the sake of succinctness I will not quote them. Instead of that I will mark that even if I don't make any modifications to the spring configuration and remove the KieSession from my example, making it a simple spring hello world example, I receive one and the same error out of my IDE (Eclipse): "The hierarchy of the type BaseController is inconsistent" and if I remove the drools-spring dependency the problem disappears.
It seems to me as dependency conflict.
Does anyone experienced similar problems with drools+spring?
Can someone suggest a solution to the problem?
Am I doing something wrong?
Thanks for the help!
After some research I found two things.
Drools' drools-spring package declares its own spring dependencies that are overriding my spring dependencies, which leads to spring malunctions. What I did is to manually remove the spring dependencies from drools-spring .pom file.
Another mistake that I had in the upper example is that I didn't have kie-spring as dependency. Kie-spring is mandatory for one drools bean KModuleBeanFactoryPostProcessor, which is responsible to read my kmodule-kbase-ksession configuration from the spring configuration.
After resolving these two problems my project compiles now and I can see in the code that KModuleBeanFactoryPostProcessor defines that my configuration is being read and analized as I expected it to be.
I write an addition to JAX-RS and included the Java EE 6 API as a Maven dependency.
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
Then I have a little test case:
#Test
public void testIsWriteable() {
class SpecialViewable extends Viewable {
public SpecialViewable() {
super("test");
}
}
FreeMarkerViewProcessor processor = new FreeMarkerViewProcessor(null);
assertTrue(processor.isWriteable(SpecialViewable.class, null, null,
MediaType.WILDCARD_TYPE));
}
But I get an error:
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ws/rs/core/MediaType
...
If I include Jersey as a JAX-RS implementation instead of the Java EE API everything is fine.
Thanks to BalusC's hint I know what I had guessed: Java EE 6 is only an API without method bodies:
From the java.net blog
You can compile you code with this
jar, but of course you cannnot run
your application with it since it
contains only the Java EE 5 APIs and
does not contain any method bodies. If
you try to run, you would get this
exception:
Exception in thread "main"
java.lang.ClassFormatError: Absent
Code attribute in method that is not
native or abstract in class file
javax/mail/Session
In order to execute a Java EE 5
application, you'll still need a Java
EE 5 container, like for example the
GlassFish application server.
I've tried to add Jersy with test scope but it didn't work.
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey-version}</version>
<scope>test</scope>
</dependency>
How can I test software that depends only on the official Java EE API?
Solution
The provider (Jersey) needs to be placed before the API (javeee-api) in the pom.xml.
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>${jersey-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
Not sure this will solve your problem but GlassFish Embedded provides a Java EE 6 implementation. Add this to your pom.xml:
<project>
...
<repositories>
<repository>
<id>glassfish-extras-repository</id>
<url>http://download.java.net/maven/glassfish/org/glassfish/extras</url>
</repository>
</repositories>
...
<dependencies>
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
...
</dependencies>
...
</project>
It's important to declare the glassfish-embedded-all artifact before the javaee-api.
As for me, JBoss' implementation is smaller than the whole Glassfish, so I'm using:
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>${version.jboss-javaee-6.0}</version>
<type>pom</type>
</dependency>
<scope>test</scope> should also do no harm.
An alternative that is JSR provider agnostic is
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
This allows you to swap Jersey with a different provider. For Glassfish 3.1.2, it uses jersey-server 1.11, which uses jsr311 version 1.1 according to the jersey pom.