Why does a method with return type List<String> return a JSON but return type of String return a html? - spring-boot

I am new to learning springboot. I have a simple #Restcontroller which has two end points /hello and /helloworld.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#SpringBootApplication
#RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#GetMapping(path = "/hello")
public String sayHelo(){
return "Hello";
}
#GetMapping(path = "/helloworld")
public List<String> sayHelloWorld(){
return List.of(
"Hello","World"
);
}
}
When I go to localhost:8080/hello I am getting the response as a html page.
But when I go to localhost:8080/helloworld the response is a JSON.
I do not understand why the first request I am getting as a html and the second as a JSON.
I was expecting a JSON in the first request as well.

Related

Fixed : spring mvc queries not found in postman because it is not in the same paquage

i am new in spring world and i have implemented a method but when i go to browser and click
http://localhost:8081/SpringMVC/servlet/aaa
i get this error message :
{
"timestamp": "2020-12-26T23:16:53.052+00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/SpringMVC/servlet/aaa"
}
I have tried two methods but still i am facing the same message
here my controller:
package t.esprit.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import tn.esprit.entities.Contrat;
import tn.esprit.entities.Departement;
import tn.esprit.entities.Employe;
import tn.esprit.entities.Entreprise;
import tn.esprit.services.IEmployeService;
import tn.esprit.services.IEntrepriseService;
#SpringBootApplication(scanBasePackages={
"tn.esprit"})
#RestController
public class RestControlEmploye {
#Autowired
IEmployeService empService;
#Autowired
IEntrepriseService entService;
/* #PostMapping("/ajouterEmployer")
#ResponseBody
public Employe ajouterEmploye(#RequestBody Employe emp){
empService.ajouterEmploye(emp);
return emp;
}
#PostMapping("/affecterEmployerDepartement/{employeId}/{depId}")
#ResponseBody
public Employe affecterEmployeADepartement(#RequestParam("user-id")int employeId,#RequestParam("user-id") int depId) {
return empService.affecterEmployeADepartement(employeId, depId);
}
#PostMapping("/ajouterContrat")
#ResponseBody
public int ajouterContrat(#RequestBody Contrat contrat) {
return empService.ajouterContrat(contrat);
}
#PostMapping("/affecterContratEmployer/{contratId}/{employeId}")
#ResponseBody
public void affecterContratAEmploye(#RequestParam("contratId")int contratId,#RequestParam("employeId")int employeId) {
empService.affecterContratAEmploye(contratId, employeId);
}
#PostMapping("/affecterContratEmployer/{employeId}")
#ResponseBody
public String getEmployePrenomById(#RequestParam("employeId")int employeId) {
return empService.getEmployePrenomById(employeId);
}
#GetMapping("/getNombreEmployeJPQL")
#ResponseBody
public long getNombreEmployeJPQL() {
return empService.getNombreEmployeJPQL();
}
#GetMapping("/getAllEmploye")
public List<Employe> listemploye() {
List<Employe> list = empService.listemploye();
return list;
}
#PostMapping("/affecterEmployeDepartement")
#ResponseBody
public void affecterEmployeDepartement(#RequestBody Employe user, #RequestBody Departement dep) {
empService.affecterEmployeDepartement(user, dep);
}
#GetMapping("/getAllEmployeByEntreprise")
#ResponseBody
public List<Employe> getallEmployebyEntreprise(#PathVariable("identr")int identr) {
return empService.getallEmployebyEntreprise(identr);
}
#PutMapping("/mettreAjourEmailByEmployeId")
#ResponseBody
public void mettreAjourEmailByEmployeId(#RequestParam("email")String email, #RequestParam("employeId")int employeId) {
empService.mettreAjourEmailByEmployeId(email, employeId);
}
#GetMapping("/getEmployeById/{employeId}")
#ResponseBody
public Employe getEmployeById( #PathVariable("employeId") int employeId) {
return empService.getEmployeById(employeId);
}
#DeleteMapping("/deleteEmployeById/{id}")
#ResponseBody
public void deleteEmployerById(#RequestParam("id") int id) {
empService.deleteEmployerById(id);
}
#DeleteMapping("/deleteEmployeContractById/{id}")
#ResponseBody
public void deleteEmployerContractById(#RequestParam("id") int id) {
empService.deleteEmployerContractById(id);
}
*/
/*#GetMapping("getAllEmployeNames")
public List<String> getAllEmployeNamesJPQL() {
List<String> list = empService.getAllEmployeNamesJPQL();
return list;
}*/
#RequestMapping(value="/aaa", method= RequestMethod.GET, produces = "application/json; charset=utf-8")
public List<String> getAllEmployeNamesJPQL() {
List<String> list = empService.getAllEmployeNamesJPQL();
return list;
}
}
i do not understand what is happening , i launched my application as a spring boot application and tried man of those different queries but i still get the same result , for idea my database and apache server are active and working fine and the my repositories working fine too , just the urls none worked for me!
here my application properties file:
#Server configuration
server.servlet.context-path=/SpringMVC
spring.mvc.servlet.path=/servlet
server.port=8081
### DATABASE ###
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/timesheet?useUnicode=true&useJDBCCo
spring.datasource.username=root
spring.datasource.password=
### JPA / HIBERNATE ###
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#Web configuration
spring.mvc.view.prefix=/views/
spring.mvc.view.suffix=.jsp
#logging configuration
logging.level.tn.esprit.service=debug
logging.level.tn.esprit.repository=warn
logging.level.root=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %-5level - %logger{36} - %msg%n
logging.file=C:\logs\springboot.log
what am i missing???? why postman and my browser can not catch the queries?
You should add #RequestMapping annotation on top of your class and this parameter should be "/SpringMVC/servlet/{function extension}". For this function "aaa" as you show.
import java.util.List;
#SpringBootApplication(scanBasePackages={"tn.esprit"})
#RestController
#RequestMapping("/SpringMVC/servlet")
public class RestControlEmploye {
#Autowired
IEmployeService empService;
#Autowired
IEntrepriseService entService;
#RequestMapping(value="/aaa", method= RequestMethod.GET, produces = "application/json; charset=utf-8")
public List<String> getAllEmployeNamesJPQL() {
List<String> list = empService.getAllEmployeNamesJPQL();
return list;
}
}

How to make post request in apache camel rest

I am new apache rest dsl with spring boot, have made following changes
Main Class
package com.javaoutofbounds.pojo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.ccs.batchfile"})
public class BatchFileApplication {
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
}
Service class
package com.ccs.batchfile.service;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile").consumes("application/json").produces("application/json").get("/routeStart").to("direct:startRoute");
}
}
Route class
package com.ccs.batchfile.routes;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ccs.batchfile.processor.StartRouteProcessor;
#Component
public class StartRoute extends RouteBuilder{
#Autowired
private StartRouteProcessor startRouteProcessor;
#Override
public void configure() throws Exception {
from("direct:startRoute").log("Inside StartRoute")
.process(startRouteProcessor);
}
}
Processor class
package com.ccs.batchfile.processor;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.springframework.stereotype.Component;
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor{
public void process(Exchange exchange) throws Exception {
String message = exchange.getIn().getBody(String.class);
System.out.println(message);
}
}
I am not getting control to StartRouteProcessor, when i make below post request in postman
http://localhost:8080/batchFile/routeStart/
I have used below test payload to check if works.
{
"title" : "test title",
"singer" : "some singer"
}
When i post the above request i am getting 404 error. Kindly help on this please
I tried your example and you need to add two changes.
In your "main" class, the 'component scan' annotation is right, but you have to add a 'ServletRegistrationBean' with name 'CamelServlet':
package org.funcode.app.main;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
#SpringBootApplication(scanBasePackages = {"org.funcode.app"})
public class BatchFileApplication {
private static final String CAMEL_URL_MAPPING = "/api/*";
private static final String CAMEL_SERVLET_NAME = "CamelServlet";
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean registration =
new ServletRegistrationBean(new CamelHttpTransportServlet(), CAMEL_URL_MAPPING);
registration.setName(CAMEL_SERVLET_NAME);
return registration;
}
}
And if you want view on the log the content you posted on the request, you need to change the method of the request to "post":
package org.funcode.app.main;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile")
.consumes("application/json")
.produces("application/json")
.post("/routeStart")
.to("direct:startRoute");
}
}
I hope it helps.

Spring boot rest : Circular view path [error]: would dispatch back to the current handler URL [/error] again

My issue is I get 404 error when calling the spring boot application on localhost:8080/users
package com.myproj.users.controller;
import java.nio.file.attribute.UserPrincipalNotFoundException;
import java.security.Principal;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.myproj.users.Greeting;
import com.myproj.users.PhysicalCharacteristicsRepository;
import com.myproj.users.UserRepository;
import com.myproj.users.UserResource;
#RestController
#RequestMapping("/users")
public class UserRestController {
private UserRepository userRepository;
private PhysicalCharacteristicsRepository characteristicsRepository;
#RequestMapping(value = "/greeting/", method = RequestMethod.GET)
public String greeting() throws UserPrincipalNotFoundException {
return "Greeting";
}
#RequestMapping(value = "/error/")
public String error() {
return "Error handling";
}
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping(method = RequestMethod.GET)
public #ResponseBody Greeting sayHello(#RequestParam(value = "name", required = false, defaultValue = "Stranger") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
#Autowired
UserRestController(UserRepository userRepository, PhysicalCharacteristicsRepository characteristicsRepository) {
this.userRepository = userRepository;
this.characteristicsRepository = characteristicsRepository;
}
}
package com.myproj.users.controller;
import java.nio.file.attribute.UserPrincipalNotFoundException;
import org.springframework.hateoas.VndErrors;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import com.weather.exceptions.UserNotFoundException;
#ControllerAdvice
class UserControllerAdvice {
#ResponseBody
#ExceptionHandler(UserNotFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
VndErrors userNotFoundExceptionHandler(UserNotFoundException ex) {
return new VndErrors("error", ex.getMessage());
}
#ResponseBody
#ExceptionHandler(UserPrincipalNotFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
VndErrors userPrincipalNotFoundException(UserPrincipalNotFoundException ex) {
return new VndErrors("error", ex.getMessage());
}
}
package com.myproj.users;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
I have tested the spring project in https://spring.io/guides/gs/actuator-service/ and it worked so I ignore what's going on.
I have defined a controller to manage errors. I have copied it from Spring Boot Remove Whitelabel Error Page
The new Application class is the following :
package com.test;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#Configuration
#ComponentScan(basePackages = "com.test")
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages = "com.test")
#EntityScan(basePackages = "com.test")
public class Application {
static final Logger logger = LogManager.getLogger(Application.class.getName());
public static void main(String[] args) {
logger.debug("Entered the application");
SpringApplication.run(Application.class, args);
}
private Application() {
}
}
As you can see I have added a controller in ComponentScan as follows :
#ComponentScan(basePackages = "com.test")
#EnableJpaRepositories(basePackages = "com.test")
#EntityScan(basePackages = "com.test")
To test I used curl curl http://localhost:9002/eleves/Hammami/ and firefox.
Changing #Controller to #RestController solved my issue.
In my case I was using thymeleaf(MVC), after that I switched to pure backend.

Spring-Boot - Error Handling

I'm trying to write error handler in Spring-Boot for my controllers that would catch most possible errors (Spring, sql etc.). So far I'm able to get JSON response with Nulls however i'm unable to put any data inside. When I try to get error message in I just receive a blank page.
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
#RestController
public class BasicErrorController implements ErrorController {
private static final String ERROR_PATH = "/error";
#RequestMapping(value=ERROR_PATH)
#ExceptionHandler(value = {NoSuchRequestHandlingMethodException.class, SQLException.class, IOException.class, RuntimeException.class, Exception.class})
public ErrorBody defaultErrorHandler(HttpServletRequest request, Exception e) {
ErrorBody eBody = new ErrorBody();
eBody.setMessage(e.getCause().getMessage());
return eBody;
}
}
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
public class ErrorBody {
private String dateTime;
private String exception;
private String url;
private String message;
}
Yo can do something like this:
#ControllerAdvice
public class ControllerExceptionTranslator {
#ExceptionHandler(EntityNotFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
#ResponseBody
SimpleErrorMessage handleException(EntityNotFoundException exception){
log.debug("Entity Not Found Exception {}",exception.getMessage());
log.trace(exception.getMessage(),exception);
return new SimpleErrorMessage("Entity not found","This resource was not found");
}
#ExceptionHandler({UsernameNotFoundException.class})
#ResponseStatus(HttpStatus.UNAUTHORIZED)
#ResponseBody
SimpleErrorMessage handleException(UsernameNotFoundException exception){
log.debug("Username not found {}",exception.getLocalizedMessage());
log.trace(exception.getMessage(),exception);
return new SimpleErrorMessage("Unaouthorized"," ");
}
}
I was able to get to data about errors and send them as json properly by using "HttpServletRequest request" and reading information from request.
#RequestMapping(value = ERROR_PATH)
public ErrorBody defaultErrorHandler(HttpServletRequest request) {....}
Here this is an example of #ExceptionHandler(Exception.class)
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
You can use #ControllerAdvice
package demo.controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
#ControllerAdvice
public class ExceptionControllerAdvice {
#InitBinder
public void initBinder(WebDataBinder binder) {
System.out.println("controller advice: init binder");
}
#ExceptionHandler(Exception.class)
public String exception(Exception e) {
System.out.println("controller advice: exception Handler");
System.out.println(e.getMessage());
return "error";
}
#ModelAttribute
public void modelAttribute(){
System.out.println("controller advice:model Attribute");
}
}

Rest easy response status + body

I have following method in my rest service:
#POST
#Path("/create")
#ResponseStatus(HttpStatus.CREATED)
#Consumes(MediaType.WILDCARD)
public String create( .... ) {.... return json;}
so I want to get a response with json in body and status code CREATED.
The problem is: I can't get a response the CREATED status.
The status code is allways OK, so it seems that "#ResponseStatus(HttpStatus.CREATED)" is just ignored...
Can somebody help me with it?
I'm using hibernate 4.1, spring 3.1 and resteasy 2.3
As far as I know, it's not possible to achieve this by annotating the method with #org.springframework.web.bind.annotation.ResponseStatus.
You can return javax.ws.rs.core.Response from your method:
return Response
.status(Response.Status.CREATED)
.entity("ok")
.build();
Or you can have org.jboss.resteasy.spi.HttpResponse injected, and set the status code directly.
There might be more ways of doing this, but I'm only aware of these two.
Working testcase:
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.interception.PostProcessInterceptor;
import org.junit.Assert;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
public class ResponseTest {
#Path("/")
public static class Service {
#Context HttpResponse response;
#GET
#Path("/1")
public Response createdUsingResponse() throws NotFoundException {
return Response
.status(Response.Status.CREATED)
.entity("ok")
.build();
}
#GET
#Path("/2")
public String created() throws NotFoundException {
response.setStatus(Response.Status.CREATED.getStatusCode());
return "ok";
}
}
public static class Interceptor implements PostProcessInterceptor {
#Context HttpResponse response;
#Override
public void postProcess(ServerResponse response) {
if(this.response.getStatus() != 0){
response.setStatus(this.response.getStatus());
}
}
}
#Test
public void test() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(new Service());
dispatcher
.getProviderFactory()
.getServerPostProcessInterceptorRegistry()
.register(new Interceptor());
{
MockHttpRequest request = MockHttpRequest.get("/1");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals(201, response.getStatus());
}
{
MockHttpRequest request = MockHttpRequest.get("/2");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals(201, response.getStatus());
}
}
}

Resources