How to use #PathParam? - json

I am following simple steps of tutorial and till now I cant figure out why it displays error.
I am trying to return simple JSON using a simple JAX-RS application.
The following is my code and web.xml settings:
package ws;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
#Path("/employee/{empno}")
public class EmployeeResource {
#Context
private UriInfo context;
public EmployeeResource() {
}
#GET
#Produces("application/json")
public String getJson( #PathParam("empno") int empno) {
switch(empno) {
case 1 :
return "{'name':'George Koch', 'age':58}";
case 2:
return "{'name':'Peter Norton', 'age':50}";
default:
return "{'name':'unknown', 'age':-1}";
}
}
#PUT
#Consumes("application/json")
public void putJson(String content) {
}
}
web.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
version="3.0">
<servlet>
<servlet-name>Jersey REST Service</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>ws</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
And then I use address:
localhost:8084/restdemo/resources/employee/empno=1
but it shows 404 error.

Call
localhost:8084/restdemo/resources/employee/1
A #PathParam is not a #QueryParam. Its name is derived from its position in the query path, not by a give name like empno=1. Since your #Path is
#Path("/employee/{empno}")
the element of your URL path that is at the position of {empno} is automatically assigned to your #PathParam empno.
Edit:
If you want to call a URL like
localhost:8084/restdemo/resources/employee?empno=1
you must use
#Path("/employee")
public String getJson(#QueryParam("empno") int empno)
Note the ? that is the border between the URL path left of it and the query on the right of it.
Hint:
Your JSON is not valid. You must use double quotes " instead of single quotes ':
return "{\"name\":\"George Koch\", \"age\":58}";

Related

How to expose service with spring 5?

I want to expose service with Spring framework (not with spring boot). Then i can use the service to feed a dashboard. Charts in the dashboard need data with json format. My question is similar to this topic but with more question about code.[question]: Expose Service Layer directly in spring mvc
I first did the model, repository to access database. I am using Hibernate and MySQL. I run my application with a class containing the main method. Then i tried to add a rest controller to access the method findAll. But when i deployed the application on Tomcat, i only get the message 404 not found.
This is my first controller
#RestController
#RequestMapping("/fruit")
public class FruitController {
#Autowired
private IFruitRepository fruitRepo = new FruitRepository();
#RequestMapping( value = "/all", method = RequestMethod.GET )
public #ResponseBody List<Port> getFruit() {
List<Fruit> res = fruitRepo.findAll();
return res;
}
}
this is the interface
public interface IFruitRepository {
Boolean create(Fruit p);
Fruit findById(int id);
List<Fruit> findAll();
Fruit update(Fruit f);
boolean delete(int id);
}
this is the implementation of findAll method
public List<Fruit> findAll(){
List<Fruit> à_retourner = new ArrayList<>();
try (SessionFactory factory = HibernateUtil.getSessionFactory()) {
Session session = factory.openSession();
Query query = session.createQuery("from Fruit");
à_retourner = query.getResultList();
} catch (Exception e) {
System.out.println("exception _ findAll _ Fruit : " + e);
}
return à_retourner;
}
EDIT:
web .xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
dispacher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
applicationcontext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
Should i add servlet , dispacher servlet , application context to find the resource through URI ?
I don't know what is exactly the url you are using to test the service but if you are trying to invoke /fruit/all, it won't work because the servlet dispatcher is configured to handle request that ends with .form. To make it work you should change the url-pattern of the servlet dispatcher to something like /fruit/*

Getting Jersey 2.x POJO JSON support to work with Jetty

I'm new RESTful web services and have been playing around with Jersey and Heroku (which uses a Jetty stack). I'm writing a simple REST API which returns a Map<String,String> in JSON for a GET request.
I'm however running into a 500 eror. The error message is :
HTTP Status 500 - org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class java.util.LinkedHashMap, genericType=java.util.HashMap.
Below is the code snippet for my resource :
#GET
#Produces("application/json")
public HashMap<String,String> getIt() {
HashMap<String,String> nameValue = new LinkedHashMap<String,String>();
nameValue.put("Alpha","One");
return nameValue;
}
Below is my web.xml file:
<web-app 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"
version="3.0">
<servlet>
<servlet-name>Jersey Web 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>org.example.services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Here is my Main class
public class Main {
public static void main(String[] args) throws Exception{
// The port that we should run on can be set into an environment variable
// Look for that variable and default to 8080 if it isn't there.
String webPort = System.getenv("PORT");
if (webPort == null || webPort.isEmpty()) {
webPort = "8080";
}
final Server server = new Server(Integer.valueOf(webPort));
final WebAppContext root = new WebAppContext();
root.setContextPath("/");
// Parent loader priority is a class loader setting that Jetty accepts.
// By default Jetty will behave like most web containers in that it will
// allow your application to replace non-server libraries that are part of the
// container. Setting parent loader priority to true changes this behavior.
// Read more here: http://wiki.eclipse.org/Jetty/Reference/Jetty_Classloading
root.setParentLoaderPriority(true);
final String webappDirLocation = "src/main/webapp/";
root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml");
root.setResourceBase(webappDirLocation);
server.setHandler(root);
server.start();
server.join();
}
}
Even after browsing through previous Stackoverflow answers like this or this, I could not find a way to solve my problem as they do not address Jersey 2.x with Jetty. I've added the following to my pom.xml file, however the problem still persists as unable to register the JSON bindings with the Jetty server.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
Automatic registration of providers by moxy didn't work as stated by Jersey Reference.
As per what they have stated, only moxy and jackson has POJO to JSON conversion feature.
Documentation says Jackson doesn't auto register(Not a problem any way!)
1. Swap Moxy with Jackson in POM.XML
Remove :
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>${jersey.version}</version>
</dependency>
Add:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
2. Register Jackson Message Body Readers and Writers :
Add org.codehaus.jackson.jaxrs to provider packages list. Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
<servlet>
<servlet-name>Web app name</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.myorg.myproj.api;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Web app name</servlet-name>
<url-pattern>/v1/*</url-pattern>
</servlet-mapping>
P.S.
I am not promoting jackson, just that moxy didn't work for me, its writers failed to auto register as they advertised and could not find documentation about manual registration!
If using Jackson Implementation
As per the Jersey Documentation - Note that there is a difference in namespaces between Jackson 1.x (org.codehaus.jackson) and Jackson 2.x (com.fasterxml.jackson).
If you are using jackson 2.x, you need to register com.fasterxml.jackson.jaxrs as init param to the ServletContainer in your web.xml as follows:
<servlet>
<servlet-name>RESTServlet</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.fasterxml.jackson.jaxrs</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

JSON Response with Spring 3 MVC and jQuery

I have some huge trouble receiving JSON from my simple Spring Controller although I checked against many other tutorials and even the official spring blog and could not find any difference, so please help me.
So my dependencies in my project are:
spring-context 3.2.2 RELEASE
spring-web 3.2.2 RELEASE
spring-webmvc 3.2.2 RELEASE
spring-test 3.2.2 RELEASE
junit 4.10
servlet-api 2.5
atmosphere-runtime 1.1.0 RC4
logback-classic 1.0.13
libthrift 0.9.0
jackson-mapper-asl 1.9.12
jackson-core-asl 1.9.12
My Controller is very simple and just generates a random UUID and returns it. It looks as follows:
#Controller
public class SimpleController {
#RequestMapping(value="/new", method=RequestMethod.GET)
public #ResponseBody SimpleResponse new() throws JsonGenerationException, JsonMappingException, IOException {
SimpleResponse sr = new SimpleResponse();
sr.setId(UUID.randomUUID().toString());
return sr;
}
}
The model is just a simple POJO like
public class SimpleResponse {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Configuration is done like this
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_2_5.xsd"
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<display-name>SimpleTest</display-name>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
and
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="de.tum.ibis.wsc" />
</beans>
So thats the server side. On the client side I have a html page with just one line of jQuery code
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="http://code.jquery.com/jquery.js"></script>
<script>
$(document).ready(function() {
$.getJSON("http://localhost:8080/Frontend/app/new", function(data) { console.log("it works"); });
});
</script>
</head>
<body>
</body>
</html>
Now according to everything I have read this should work but it does not for me. If I call localhost:8080/Frontend/app/new directly in my browser I get something like this: {"id":"b46b8d67-5614-44ed-90ef-d2da14d260f6"} and Firebug tells me that the response header from the server is
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Server: Jetty(7.6.5.v20120716)
so content-type should be fine. Well if I now run the jquery ajax call I get the error "JSON.parse: unexpected end of data " in jquery.js and I have no cloue why. I hope anybody can help me with that. Thanks!
------ Update ------
Firebug: jQuery error
Firebug: All I get
Firebug: This is what I get if a access the url directly
Try configuring ContentNegotiationManagerFactoryBean in Spring XML config, see Spring docs
Set favorPathExtension to false and update method's #RequestMapping like so
#RequestMapping(value="/new", method=RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
In your AJAX request, you're using
http://localhost:8080/Frontend/app/new
And your servlet declares URL "/new", you should use "/app/new" instead.
#RequestMapping(value="/app/new", method=RequestMethod.GET)

Unicode characters are being saved incorrectly

I have a mysql database with unicode text strings in it. My JSF application (running on tomcat 6) can read these unicode strings out and display them correctly in the browser. All the html charsets are set to UTF-8.
When I save my object, even having made no changes, Hibernate persists it back to the database. If I look directly in the database now, I see that characters with accents have become junk.
My database connection string is:
<property name="hibernate.connection.url"
value="jdbc:mysql://database.address.com/dbname?autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf8"/>
Changing that characterEncoding to UTF-8 instead of utf8 makes no difference.
Actually it was working days ago for sure, but now it isn't and I'm out of ideas for what to check. Do you have any suggestions? I can provide any further info deemed relevant.
Does it only happen on certain tables? Perhaps the DEFAULT CHARSET of those tables is different than the others. (http://dev.mysql.com/doc/refman/5.1/en/charset-table.html)
Some options to resolve that come to my mind:
if using facelets, specify <?xml version="1.0" encoding="UTF-8"?> at the top of the page
if using JSP, specify <%# page pageEncoding="utf-8" %>
if that does not work, make a filter that is mapped to the faces servlet, and does request.setCharacterEncoding("utf-8")
I had the same problem as you but with PostgreSQL. You can use filter as below. It worked for me. I think that it must be better solution for that, but i haven't found yet :/
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class UnicodeFilter implements Filter {
#Override
public void destroy() {}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
// Set the characterencoding for the request and response streams.
req.setCharacterEncoding("UTF-8");
res.setContentType("text/html; charset=UTF-8");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig arg0) throws ServletException {}
}
In web.xml:
<filter>
<filter-name>utffilter</filter-name>
<filter-class>utils.UnicodeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>utffilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
In Spring a simplest solution i've found is CharacterEncodingFilter.
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Ensure UTF-8 encoded pages so that certain characters are displayed
and submitted correctly...
Add this filter to web.xml.
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Jersey implementing ContextResolver<JAXBContext> in Spring

So I am writing a Spring(2.5( + Jersey(1.1.4.1) and trying to create a JSONConfiguration using a ContextResolver. Here is the code:
package com.rhigdon.jersey.config;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
#Provider
public final class JAXBContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
public JAXBContextResolver() throws Exception {
this.context = new JSONJAXBContext(JSONConfiguration.mappedJettison().build(), "com.rhigdon.core.model.");
}
public JAXBContext getContext(Class<?> aClass) {
return context;
}
}
Unfortunately my app is still returning the default mapping:
{"id":"1","question":"What is/was the
name of your first pet?"}
When I debug the application it never actually hits this code. Is this due to using the SpringServlet? Here is my Jersey Config in my web.xml:
<servlet>
<servlet-name>Jersey Spring Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Spring Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Anyone have a similar setup with JSONConfiguration working?
You need to register your provider in your spring context:
<bean class="com.company.jersey.config.JAXBContextResolver"/>
Or, if you are using annotation-based configuration, you need to annotate your provider class with #Component and include something like
<context:annotation-config />
<context:component-scan base-package="com.company.jersey" />
to your application context configuration.
I'm using jersey version 1.10 and I don't have the #Component annotation nor the bean definition, and it works without it.
Jersey REST Service
com.sun.jersey.spi.spring.container.servlet.SpringServlet
com.sun.jersey.config.property.packages
ca.gc.cbsa.ezfw.foundation.webservice
1