2
I have a Spring MVC aplication. I want to convert it to a RESTful 

webservice, which returns a JSON response. Can somebody help me with this??

Basically, I want to convert my controller to a REST controller.

My Code :

///////////////////////////PersonController//////////////////////////////

package com.journaldev.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.journaldev.spring.model.Person;
import com.journaldev.spring.service.PersonService;

@Controller
public class PersonController {

    private PersonService personService;

    @Autowired(required=true)
    @Qualifier(value="personService")
    public void setPersonService(PersonService ps){
        this.personService = ps;
    }

    @RequestMapping(value = "/persons", method = RequestMethod.GET)
    public String listPersons(Model model) {
        model.addAttribute("person", new Person());
        model.addAttribute("listPersons", this.personService.listPersons());
        return "person";
    }

    //For add and update person both
    @RequestMapping(value= "/person/add", method = RequestMethod.POST)
    public String addPerson(@ModelAttribute("person") Person p){

        if(p.getId() == 0){
            //new person, add it
            this.personService.addPerson(p);
        }else{
            //existing person, call update
            this.personService.updatePerson(p);
        }

        return "redirect:/persons";

    }

    @RequestMapping("/remove/{id}")
    public String removePerson(@PathVariable("id") int id){

        this.personService.removePerson(id);
        return "redirect:/persons";
    }

    @RequestMapping("/edit/{id}")
    public String editPerson(@PathVariable("id") int id, Model model){
        model.addAttribute("person", this.personService.getPersonById(id));
        model.addAttribute("listPersons", this.personService.listPersons());
        return "person";
    }

}

/////////////////////////////////PersonDAO/////////////////////////////

package com.journaldev.spring.dao;

import java.util.List;

import com.journaldev.spring.model.Person;

public interface PersonDAO {

    public void addPerson(Person p);
    public void updatePerson(Person p);
    public List<Person> listPersons();
    public Person getPersonById(int id);
    public void removePerson(int id);
}

///////////////////////////////PersonDAOImpl/////////////////////////

package com.journaldev.spring.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.journaldev.spring.model.Person;

@Repository
public class PersonDAOImpl implements PersonDAO {

    private static final Logger logger = LoggerFactory.getLogger(PersonDAOImpl.class);

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sf){
        this.sessionFactory = sf;
    }

    @Override
    public void addPerson(Person p) {
        Session session = this.sessionFactory.getCurrentSession();
        session.persist(p);
        logger.info("Person saved successfully, Person Details="+p);
    }

    @Override
    public void updatePerson(Person p) {
        Session session = this.sessionFactory.getCurrentSession();
        session.update(p);
        logger.info("Person updated successfully, Person Details="+p);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Person> listPersons() {
        Session session = this.sessionFactory.getCurrentSession();
        List<Person> personsList = session.createQuery("from Person").list();
        for(Person p : personsList){
            logger.info("Person List::"+p);
        }
        return personsList;
    }

    @Override
    public Person getPersonById(int id) {
        Session session = this.sessionFactory.getCurrentSession();      
        Person p = (Person) session.load(Person.class, new Integer(id));
        logger.info("Person loaded successfully, Person details="+p);
        return p;
    }

    @Override
    public void removePerson(int id) {
        Session session = this.sessionFactory.getCurrentSession();
        Person p = (Person) session.load(Person.class, new Integer(id));
        if(null != p){
            session.delete(p);
        }
        logger.info("Person deleted successfully, person details="+p);
    }

}

//////////////////////////////////Person(Model)///////////////////////

package com.journaldev.spring.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Entity bean with JPA annotations
 * Hibernate provides JPA implementation
 * @author pankaj
 *
 */
@Entity
@Table(name="PERSON")
public class Person {

    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    private String name;

    private String country;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Override
    public String toString(){
        return "id="+id+", name="+name+", country="+country;
    }
}

///////////////////////////////////PersonService///////////////////

package com.journaldev.spring.service;

import java.util.List;

import com.journaldev.spring.model.Person;

public interface PersonService {

    public void addPerson(Person p);
    public void updatePerson(Person p);
    public List<Person> listPersons();
    public Person getPersonById(int id);
    public void removePerson(int id);

}

//////////////////////////////ServiceImpl////////////////////////////

package com.journaldev.spring.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.journaldev.spring.dao.PersonDAO;
import com.journaldev.spring.model.Person;

@Service
public class PersonServiceImpl implements PersonService {

    private PersonDAO personDAO;

    public void setPersonDAO(PersonDAO personDAO) {
        this.personDAO = personDAO;
    }

    @Override
    @Transactional
    public void addPerson(Person p) {
        this.personDAO.addPerson(p);
    }

    @Override
    @Transactional
    public void updatePerson(Person p) {
        this.personDAO.updatePerson(p);
    }

    @Override
    @Transactional
    public List<Person> listPersons() {
        return this.personDAO.listPersons();
    }

    @Override
    @Transactional
    public Person getPersonById(int id) {
        return this.personDAO.getPersonById(id);
    }

    @Override
    @Transactional
    public void removePerson(int id) {
        this.personDAO.removePerson(id);
    }

}
N V
  • 122
  • 1
  • 2
  • 12
  • 1
    You don't "convert" a controller. You define your API, then you create the appropriate controllers. Except for some service calls those controllers will have nothing in common with the existing ones. So there is actually nothing to convert. – a better oliver Nov 07 '16 at 14:15

3 Answers3

3

First you have to add Jackson Databind dependency in your pom file then you can define your rest controller for exemple :

 @RestController
    public class PersonRestService {
        @Autowired
    private PersonService personService ;

        @RequestMapping(value="/persons",method=RequestMethod.POST)
        public Person addPerson(@RequestBody  Person Person) {
            return personService.addPerson(Person);
        }
       @RequestMapping(value="/persons",method=RequestMethod.Delete)
        public void deletePerson(int code) {
            personService.deletePerson(code);
        }
       @RequestMapping(value="/persons",method=RequestMethod.GET)
        public Person getPerson(@RequestParam int code) {
            return personService.getPersonById(code);
        }
       @RequestMapping(value="/allPersons",method=RequestMethod.GET)
        public List<Person> getAllPerson() {
            return personService.getAllPerson();
        }

    }
e2rabi
  • 4,728
  • 9
  • 42
  • 69
  • Errors aside, this is not RESTful. Your controller exposes a resource that can be both a list and a single person. How can it be both? – a better oliver Nov 07 '16 at 14:24
  • For the list of persons I use /allPersons and for single person I use /persons?code=id ? where is the errors I know that is not a part of rest specifications but it work – e2rabi Nov 07 '16 at 14:31
  • You are right about `allPersons`. But that's not enough. You need to use something like `/persons/{code}` for the other requests. That makes every person a different resource. That's the point of REST. If you use query parameters the resource stays the same. But obviously there is more than just one person. – a better oliver Nov 07 '16 at 14:42
  • I think if I change param in my method getPerson(@requestParm int code ) to getPerson(@PathVariable("code") int code ) it will give something like /persons/{code} ? – e2rabi Nov 07 '16 at 14:46
  • I'm not 100% sure what you mean, but it guess you mean the right thing. – a better oliver Nov 07 '16 at 14:49
  • you have used RequestBody with RestController, while in the example above this, Controller and ResponseBody have been used. Are both combinations correct? – N V Nov 08 '16 at 05:57
  • Yes, the both are correct, just @ResponseBody require the jackson-databind dependency to work – e2rabi Nov 08 '16 at 09:07
2

Its easy, what you need to do is add a response in JSON for all request which need it. The annotation is @ResponseBody and you can return any object, jackson will serialize it to json format for you.

For example in your code:

@RequestMapping("/remove/{id}")
@ResponseBody
public boolean removePerson(@PathVariable("id") int id){

    this.personService.removePerson(id);
    //true if everything was OK, false if some exception
    return true;
}

...

@RequestMapping(value = "/persons", method = RequestMethod.GET)
@ResponseBody
public List<Person> listPersons(Model model) {
    return this.personService.listPersons();
}

You only need to modify your controller, to make it RESTFul Also you will have to add logic to your JS code to handle the new responses values.

cralfaro
  • 5,822
  • 3
  • 20
  • 30
  • Why `return true` for OK? If no exception is thrown the request returns 200/OK anyway. – a better oliver Nov 07 '16 at 14:19
  • 1
    @zeroflagL yes i didnt want to go so deep into details, but he should use the proper codes for rest actions, 200=OK, 201=created,...but to simplify the response i didnt add it http://www.restapitutorial.com/httpstatuscodes.html – cralfaro Nov 07 '16 at 14:21
1

Simply use the annotation @RestController.

You can also refer to previously asked question on this link

Difference between spring @Controller and @RestController annotation

Community
  • 1
  • 1