Exposing data from spring, hibernate application as restful - json

The work has been derived from this link
http://www.javacodegeeks.com/2013/04/spring-mvc-hibernate-maven-crud-operations-example.html. I have tried made an attempt of releasing the data of the application in a json format for which I have made further modifications in controller class
#Controller
#RequestMapping(value="/team")
public class TeamController {
#Autowired
private TeamService teamService;
#RequestMapping(value="/add", method=RequestMethod.GET)
public ModelAndView addTeamPage() {
ModelAndView modelAndView = new ModelAndView("add-team-form");
modelAndView.addObject("team", new Team());
return modelAndView;
}
#RequestMapping(value="/add", method=RequestMethod.POST)
public ModelAndView addingTeam(#ModelAttribute Team team) {
ModelAndView modelAndView = new ModelAndView("home");
teamService.addTeam(team);
String message = "Team was successfully added.";
modelAndView.addObject("message", message);
return modelAndView;
}
#RequestMapping(value="/list")
public ModelAndView listOfTeams() {
ModelAndView modelAndView = new ModelAndView("list-of-teams");
List<Team> teams = teamService.getTeams();
modelAndView.addObject("teams", teams);
return modelAndView;
}
#RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
public ModelAndView editTeamPage(#PathVariable Integer id) {
ModelAndView modelAndView = new ModelAndView("edit-team-form");
Team team = teamService.getTeam(id);
modelAndView.addObject("team",team);
return modelAndView;
}
#RequestMapping(value="/edit/{id}", method=RequestMethod.POST)
public ModelAndView edditingTeam(#ModelAttribute Team team, #PathVariable Integer id) {
ModelAndView modelAndView = new ModelAndView("home");
teamService.updateTeam(team);
String message = "Team was successfully edited.";
modelAndView.addObject("message", message);
return modelAndView;
}
#RequestMapping(value="/delete/{id}", method=RequestMethod.GET)
public ModelAndView deleteTeam(#PathVariable Integer id) {
ModelAndView modelAndView = new ModelAndView("home");
teamService.deleteTeam(id);
String message = "Team was successfully deleted.";
modelAndView.addObject("message", message);
return modelAndView;
}
#RequestMapping(value = "/api/team", method = RequestMethod.GET)
// public #ResponseBody String listUsersJson (ModelMap model) throws JSONException {
public #ResponseBody
String listTeamJson () throws JSONException {
JSONArray userArray = new JSONArray();
for (Team team : teamService.getTeams()) {
JSONObject userJSON = new JSONObject();
userJSON.put("id", team.getId());
userJSON.put("Name", team.getName());
userJSON.put("Rating", team.getRating());
userArray.put(userJSON);
}
return userArray.toString();
}
}
But This code is showing error 404. How can I implement my application in order to release the data in json format?

Change your JSON code to following:
#RequestMapping(value = "/api/team", method = RequestMethod.GET)
public #ResponseBody List<TEAMS_OBJECT_TYPE>listTeamJson () throws JSONException {
return teamService.getTeams();
}
}
NOTE: TEAMS_OBJECT_TYPE needs to be replaced by the type that teamService.getTeams() returns.
#ResponseBody will automatically convert it into JSON, so all you need to do is read it properly on client side.

Related

Mocking of new object and injecting it

I want to write junit for below method
public class ManageProfile{
public ResponseDTO create(SessionContext context, String flowId, Map<String, String> params) {
ApiClient apiClient=new ApiClient();
apiClient.setBasePath("ip");
Service service=new Service();
service.setApiClient(apiClient);
ResponseDTO response= service.createProfile(new RequestDto());
return response;
}
}
Its not spring based application.
class Test
#Test
public void testCreate() {
SessionContext sessionContext = mock(SessionContext.class);
ManageProfile manageProfile=new ManageProfile();
Service service=mock(Service.class);
when(service.createProfile(any())).thenReturn(new ResponseDTO());
String flowId = "1";
Map<String, String> params = new HashMap<>();
ResponseDTO responseDTO=manageProfile.create(sessionContext,flowId,params);
Assert.assertEquals("123"responseDTO.getId);
}
}
I am not able to inject mock Service object in ManageProfile as it is getting created using new keyword
Use spy to mock some methods in ManageProfile class
public class ManageProfile{
public ResponseDTO create(SessionContext context, String flowId, Map<String, String> params) {
ApiClient apiClient=new ApiClient();
apiClient.setBasePath("ip");
Service service = createService();
...
}
public Service createService(){
return new Service();
}
class Test {
#Test
public void testCreate() {
SessionContext sessionContext = mock(SessionContext.class);
ManageProfile manageProfile= spy(new ManageProfile());
Service service=mock(Service.class);
when(mangaeProfile.createService()).thenReturn(service);
...
}

#ModelAndView is working as expected from the ui, but does not when a json request is sent by postman

I have managed to make a modelAndView in my controller doing what Im expecting from the ui, but sometimes I need to test it via post man so when I tried the model attribute is always null, can someone explain what is happening exactly?
here is the controller that im using:
#Controller
public class LoginController extends AuthenticationBase {
#Autowired
private AuthenticationInterfaceImpl authentication;
Logger logger = LoggerFactory.getLogger(LoginController.class);
#GetMapping("/login_form")
public ModelAndView login(#ModelAttribute LoginForm loginForm) {
return new ModelAndView("index");
}
#PostMapping("/login_form")
public ModelAndView login(HttpServletRequest request, HttpServletResponse response,
#ModelAttribute LoginForm loginForm, BindingResult result) {
LoginInfo loginInfo;
try {
loginInfo = authentication.userLogin(loginForm.getUserName(), loginForm.getPassword());
if (loginInfo.getNewPasswordRequired()) {
return new ModelAndView("change_password", "change_password", loginForm.getUserName());
} else {
UserInfo userInfo = new UserInfo(loginInfo.getUserName(), loginInfo.getEmailAddr(), "");
return new ModelAndView("application", "application", userInfo);
}
} catch (Exception e) {
logger.error(e.getMessage());
}
return new ModelAndView("index", "authenticationError", "Password or user name error!");
}
}

How to redirect into HTML static page from the Spring Boot genericResponse method

Im very new to the Spring boot. according to the client requirement my other member developed code segment using spring boot to get user response from here. Here is the code segment.
public GenericResponse updateAcceptOrReject(String password, FileAcceptStatus status) {
// TODO Auto-generated method stub
GenericResponse genericResponse = new GenericResponse();
String sql = "SELECT * FROM employee WHERE pass_code = ?";
Employee employee = null;
try {
employee = (Employee) jdbcTemplate.queryForObject(sql, new Object[] { password }, new EmployeeRowMapper());
} catch (EmptyResultDataAccessException e) {
System.out.println("error :"+ e.getLocalizedMessage());
employee = null;
}catch (Exception e) {
System.out.println("error :"+ e.getLocalizedMessage());
employee = null;
}
// check if employee available
if(employee == null) {
genericResponse.setStatusCode(200);
genericResponse.setMessage("No employee found");
return genericResponse;
}
// check acceptStatus
if(employee.getAccept_status() != 0) {
genericResponse.setStatusCode(201);
genericResponse.setMessage("You already accepted");
return genericResponse;
}
String updateSql = "update employee set accept_status=? where pass_code=?";
int[] types = {Types.INTEGER, Types.VARCHAR};
int updatedFlag = jdbcTemplate.update(updateSql, new Object[] { status.ordinal(), password }, types);
if(updatedFlag == 1) {
genericResponse.setStatusCode(0);
genericResponse.setMessage("Success");
return genericResponse;
}else {
genericResponse.setStatusCode(-99);
genericResponse.setMessage("Error occured while updating employ");
return genericResponse;
}
}
what i want is load separate static HTML page with a Success message located in another package rather that stating Success message in genericResponse.setMessage(). likewise static pages for other messages too.
Can anyone help me here?
Controller is like
#RestController
public class HumanResourceController {
#Autowired
private HumanResourceService hRService;
#RequestMapping(value = "/update/status/{password:.+}/{status}", method = RequestMethod.GET)
public ResponseEntity<?> updateAcceptOrReject(#PathVariable("password") String password,
#PathVariable("status") FileAcceptStatus status) {
GenericResponse genericResponse = hRService.updateAcceptOrReject(password, status);
return ResponseEntity.ok().body(genericResponse);
}
}
The #RestController will always return json message, so you should change it to #Controller, then you need to create a viewresolver to render the static html
move all your html file into /WEB-INF/
#Configuration
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".html");
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
#Controller
public class HumanResourceController {
#Autowired
private HumanResourceService hRService;
#RequestMapping(value = "/update/status/{password:.+}/{status}", method = RequestMethod.GET)
public String updateAcceptOrReject(#PathVariable("password") String password,
#PathVariable("status") FileAcceptStatus status) {
GenericResponse genericResponse = hRService.updateAcceptOrReject(password, status);
// you can return various view according the generic response http code
return "alreadyaccepted";
}
}

Serializer a method just from a specify Controller - Spring, JSON Jackson

I have 2 controllers and a get method for a field with custom serialization like as #JsonSerialize(using = MySerialization.class).
But I want to make this serialization just when I call method from A Controller, not from B Controller.
How I can specify this?
Okay, I will assume that you have the follow requestmaps
#RequestMapping(value = "/saveA", method = RequestMethod.GET)
public #ResponseBody Person getPersonA() {
return getPerson();
}
#RequestMapping(value = "/saveB", method = RequestMethod.GET)
public #ResponseBody Person getPersonB() {
return getPerson();
}
private Person getPerson() {
return new Person("Elvis");
}
static class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
So you want to serialize the Person object in different ways at each requestMap, I personally could not found (even see) a Spring Solution for that, I think that is a Jackson and Java problem to be solved, so here is my solution:
Create a Person subclass then customize it as you need, for example
static class CustomPerson extends Person {
public CustomPerson(String name) {
super(name);
}
#JsonSerialize(using = NameSerializer.class)
#Override
public String getName() {
return super.getName();
}
}
static class NameSerializer extends JsonSerializer {
#Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString("customSerializer-" + String.valueOf(value));
}
}
Then, all you need to do is create a mapper method, that converts your Person to a CustomPerson
#RequestMapping(value = "/saveB", method = RequestMethod.GET)
public #ResponseBody Person getPersonB() {
return getCustomPerson();
}
private Person getCustomPerson() {
return new CustomPerson(getPerson().getName());
}
Another option is to create the object mapper and serialize the Object as you want when you need it customized:
#RequestMapping(value = "/saveC", method = RequestMethod.GET)
public void getPersonC(HttpServletResponse response) throws IOException {
response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
new ObjectMapper()
.registerModule(new SimpleModule().addSerializer(Person.class, new JsonSerializer<Person>() {
#Override
public void serialize(Person value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", "Custom-" + value.getName());
gen.writeEndObject();
}
}))
.writeValue(response.getWriter(), getPerson());
}

Spring MVC Controller adds request object to response

I am building a JSON REST service with Spring 3.0.5 and my response contains the object from my request although I did not add it. I am using the MappingJacksonJsonView and Jackson 1.6.4 for rendering the ModelAndView object to JSON.
The User object is simple
public class SimpleUser {
private String username;
private String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password;
}
}
One of the requests looks like this
#RequestMapping(value = "/register", method = RequestMethod.GET)
public ModelAndView register(SimpleUser user) {
ModelAndView mav = new ModelAndView();
mav.addObject("ok", "success");
return mav;
}
Then I call the service with
curl 'http://localhost:8080/register?username=mike&password=mike'
The response I expect is
{"ok": "success"}
The response I get is
{"ok":"success","simpleUser":{"username":"mike","password":"mike"}}
Where and why is the user object added to the ModelAndView and how can I prevent that?
Possible solution
One way to work around this is to use Model instead of SimpleUser. This seems to work but it should be possible to use the business object.
This works:
#RequestMapping(value = "/register", method = RequestMethod.GET)
public ModelAndView register(Model model) {
log.debug("register(%s,%s)", model.asMap().get("usernmae"), model.asMap().get("password"));
ModelAndView mav = new ModelAndView();
mav.addObject("ok", "success");
return mav;
}
It looks like you're trying to process a form submission and retrieve the result via ajax. If this is the case, you don't want to return a ModelAndView object. Use the #ResponseBody annotation to have Jackson represent your return object as a json object.
public #ResponseBody Map registerUser(SimpleUser user){
Map responseMap = new HashMap();
if(registerUser(user)){
responseMap.put("OK", "Success");
} else {
responseMap.put("OK", "Failure");
}
return responseMap;
}
For Spring 3.1.x You can set the modelKey property in org.springframework.web.servlet.view.json.MappingJacksonJsonView in your *servlet.xml like below:
Servlet.xml:
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="modelKey" value="appResponse"/>
</bean>
Request Method:
#RequestMapping(value="/access")
public #ResponseBody Model getAccess(Model model) {
...
model.addAttribute("appResponse", responseDetails);
...
return model;
}
When you set a specific modelKey, all other attributes attached the the model will be ignored, hence the form parameters/request parameters. In additional, this provides a clearer design if your are presenting views for multiple media types (application/xml or application/json).