How to expose service with spring 5? - mysql

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/*

Related

Spring 4 RestController & Returning JSON

I have a simple controller, which should return JSON, but is failing to do so. The JSON library is Jackson, configured as a maven dependency. When I make a request using postman, against this url path, I am receiving a 404 error. When I attempt to inspect the JSON Returned, I see "Malformed JSON: Unexpected '<'".
Could someone suggest what it is I am missing / failing to understand? Thank you
#RestController
#RequestMapping("/World/")
public class RestfulController {
#RequestMapping(value = "/Country/", method = RequestMethod.GET, produces="application/json")
public ResponseEntity<Country> findAllCountrys(){
Country c = new Country(1, "Ethiopia", "Addis Abba", "94 Million");
return new ResponseEntity<Country>(c, HttpStatus.OK);
}
}
spring application context
<beans xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.restfulapp.controller"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
</bean>
You should try this:
#RestController
#RequestMapping("/World")
public class RestfulController {
#RequestMapping(value = "/Country", method = RequestMethod.GET)
public Country findAllCountrys(){
Country c = new Country(1, "Ethiopia", "Addis Abba", "94 Million");
return c;
}
}
The request url: http://yourhost/World/Country
This should return a json of Country

javax.naming.NoInitialContextException Tomcat DataSource JNDI intellij idea 14

I am trying go get Connection Pool with Tomcat DataSource and MySQL in ntellij idea 14. I've done these steps:
Select "Project Structure" from the File menu
From there, select the "Facets" option. Make sure that you have a Web
facet configured. If not, add one.
Once the web facet is added, select "Add Application Server specific
descriptor..."
Select Tomcat Context Descriptor from the options and click OK.
I got META-INF/context.xml in web directory. I added next lines in context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/payments"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/paymentsdb"
username="root"
password="password"
maxActive="100"
maxIdle="20"
minIdle="5"
maxWait="10000"/>
</Context>
And this into 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_3_1.xsd"
version="3.1">
<!--DB Connection start-->
<description>MySQL Test App</description>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/payments</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
This is my method to get connection
public static Connection createConnection(){
Context context = null;
DataSource dataSource = null;
Connection connection = null;
try {
context = (Context) new InitialContext().lookup("java:comp/env");
dataSource = (DataSource) context.lookup("jdbc/payments");
connection = dataSource.getConnection();
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
I got this exception in line
dataSource = (DataSource)
context.lookup("java:comp/env/jdbc/payments");
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at ua.epam.kuts.dao.MySQLDAOFactory.createConnection(MySQLDAOFactory.java:22)
at Test.main(Test.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
I use Tomcat 8.0.23. Any idea? I googled for several hours and didn't find anything that helped me. Drew me mad. I checked connection with Statment and it works. I have connector.jar.
I've done stupid mistake. I was trying to test DataSource connection running it in public static main(String[] args) method instead of running it on the server. That's why InitialContext was not initialized. Found answer here in second post.

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)

How to use #PathParam?

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}";