Springboot Thymeleaf Cache page - html

I implement a client application. This application consume a Rest webservice and these service return and html page as a variable in a model.
I take these html page successfully from Rest Service and try to write to a blank html page.
My code to write html page.
public void writeToHtml(ResponseModel response) {
FileWriter fWriter = null;
BufferedWriter writer = null;
try {
fWriter = new FileWriter(src/main/resources/templates/test.html);
writer = new BufferedWriter(fWriter);
writer.write(response.getHtmlPage());
writer.newLine();
writer.close();
} catch (Exception e) {
}
}
These function can take htmlPage from ResponseModel and write successfully to test.html
Untill there everthing work properly and my controller display it on secreen.
However, if I again call same Rest service, it can again write to "test.html" but, on the screen it shows the first created html page.
Probably it cache the first html and if I rewrite again. I just take cache one.
My Controller
#RequestMapping(value = "/testPath", method = RequestMethod.POST)
public String payment(RequestModel paymentInfoModel, BindingResult bindingResult, Model model) {
RestTemplate restTemplate = new RestTemplate();
ResponseModel response = restTemplate.postForObject(url, request, ResponseModel.class);
writeToHtml(response);
return "test";
}
Could you help me to solve these issue ?
IDEA : Inteliji

I solved my problem a bit differently:
#RequestMapping(value = "/testPath", method = RequestMethod.POST, produces = "text/html")
#ResponseBody
public String payment(RequestModel paymentInfoModel, BindingResult bindingResult, Model model) {
RestTemplate restTemplate = new RestTemplate();
ResponseModel response = restTemplate.postForObject(url, request, ResponseModel.class);
writeToHtml(response);
return response.getHtmlPage();
}
So I don't need to create an HTML page.

Related

Can pass my own object with RestTemplate PUT

I want to build a small RESTful Service, send a PUT request with an Object of a class I created (MyObject), and getting a response with only status.
My controler:
#RestController
public class MyControler {
#RequestMapping(path = "/blabla/{id}", method = RequestMethod.PUT)
#ResponseBody
public ResponseEntity<String> putMethod (#PathVariable("id") Long id,
#RequestBody MyObject t) {
/*todo*/
return new ResponseEntity<String>(HttpStatus.OK);
}
My Test App
#SpringBootApplication
public class App {
public String httpPut(String urlStr) {
MyObject myObject = new MyObject(p,p,....);
URI url = null;
HttpEntity<MyObject> requestEntity;
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_JSON);
headers.setAccept(list);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Content-Type", "application/json");
requestEntity = new HttpEntity<Transaction>(t, headers);
ResponseEntity<String> response =
rest.exchange(url, HttpMethod.PUT, requestEntity, MyObject.class);
return response.getStatusCode().getValue();
}
Im getting an HttpClientErrorException: 400 Bad Request
Where is my mistake? What I want is for Spring to automaticly serialize the MyObject. MyObject class is implementing serializable.
What do I miss?
}
Maybe you're doing to much?
Did you try to put the object as json via postman or something similar? If so what is the response?
Nevertheless i created a minimal example for consuming a service via Springs RestTemplate.
This is all needed code for getting a custom object AND putting a custom object via RestTemplate
public void doTransfer(){
String url = "http://localhost:8090/greetings";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Greeting> greeting = restTemplate.getForEntity(url, Greeting.class);
LOGGER.info(greeting.getBody().getValue());
Greeting myGreeting = new Greeting();
myGreeting.setValue("Hey ho!");
HttpEntity<Greeting> entity = new HttpEntity<Greeting>(myGreeting);
restTemplate.exchange(url, HttpMethod.PUT, entity, Greeting.class);
}
I've provided a sample project with a sender (maybe not a good name .. it is the project with the greetings endpoint) and a receiver (the project which consumes the greetings endpoint) on Github
Try to do this:
ResponseEntity<MyObject> responseSerialized =
rest.exchange(url, HttpMethod.PUT, requestEntity, MyObject.class);

make mvc controller return text instead of json

I am trying to make method Spring MVC method in controller to return text instead of json.
My current method looks like this
#RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/html")
public ModelAndView uploadFile(#RequestParam("file") MultipartFile file) {
LOGGER.debug("Attempt to upload file with template.");
try {
String fileContent = FileProcessUtils.processFileUploading(file);
return createSuccessResponse(fileContent);
} catch (UtilityException e) {
LOGGER.error("Failed to process file.", e.getWrappedException());
return createResponse(INTERNAL_ERROR_CODE, e.getMessage());
}
}
But the response header content-type: application/json.
I was trying to pass HttpServletResponse to controller and set content type but it still continued to return json.
What's the problem?
What's FileProcessUtils? Google doesn't bring up anything. Is it a class created by you or your organization? It would appear that the method is returning a response with a content-type of application/json. What were you expecting it to return and why? You would have to somehow parse the json to extract the data necessary for constructing a ModelAndView or find another method that returns what you want.
But without more information on FileProcessUtils, it isn't possible to provide more of an answer.
You can either do this:
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public ResponseEntity foo() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_HTML);
return ResponseEntity.ok().headers(headers).body("response");
}
or do this:
#RequestMapping(value = "/foo", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
Both works fine.

Controller for JSON and HTML with Spring Boot

I am writing an application where among other things I need to do CRUD operations with certain objects. I need to be able to serve both HTML pages for human users, and JSON for other applications. Right now my URLs look like this for "Read":
GET /foo/{id} -> Serves HTML
GET /rest/foo/{id} -> Serves JSON
etc.
This seems a little redundant. I would rather have something like this:
GET /foo/{id}.html OR /foo/{id} -> Serves HTML
GET /foo/{id}.json -> Serves JSON
Can Spring Boot do this? If so, how?
I know how to return JSON:
#RequestMapping(value = "/foo/{id}", method = RequestMethod.GET, produces = "application/json")
public Object fetch(#PathVariable Long id) {
return ...;
}
I also know how to return HTML:
#RequestMapping("/app/{page}.html")
String index(#PathVariable String page) {
if(page == null || page.equals(""))
page = "index";
return page;
}
But I'm not sure how to have a controller do one or the other based on the request.
It's a default behavior for Spring Boot. The only thing is that you have to mark one of #RequestMapping to produce JSON. Example:
#Controller
class HelloController {
// call http://<host>/hello.json
#RequestMapping(value = "/hello", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public MyObject helloRest() {
return new MyObject("hello world");
}
// call http://<host>/hello.html or just http://<host>/hello
#RequestMapping(value = "/hello", method = RequestMethod.GET)
public String helloHtml(Model model) {
model.addAttribute("myObject", new MyObject("helloWorld"));
return "myView";
}
}
Read more at: http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc and http://spring.io/blog/2013/06/03/content-negotiation-using-views
Actually, you are mixing rest web service with html pages, it's a bad practice.
If you want to build something really great, here is my advice.
Write only CRUD operations in your controllers and all html/css/js keep in some static folder and when you will want to see ui part - just call that static index.html file
You can read more about that here - http://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot
But if you really want to do things as it is now, here is the solution:
#RequestMapping(value = "/foo/{id}", method = RequestMethod.GET)
public Object serve(final HttpServletRequest req, final HttpServletResponse resp, #PathVariable final Long id) {
String header = req.getHeader("Accept");
// If Accept header will be text/html - then we are forwarding to jsp page.
if(header.equals("text/html")) {
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
// In other cases we are returning json and setting appropriate headers.
resp.setHeader("Content-Type", "application/json");
Object object = "Some string";
return object;
}

spring mvc 3 content-type "application/json" works from client but not from unit test

I have a Rest Controller method using Spring 3.1 that looks like this:
#RequestMapping(value="/user", method=RequestMethod.POST, consumes={MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<String> addUser(#RequestBody #Valid User user){
System.out.println("called / user method");
try{
user = userService.addUser(user);
return responseBuilder.addApiResourceSucceeded(user,null);
}catch(Exception e){
return responseBuilder.apiActionFailed("user already exists", HttpStatus.CONFLICT);
}
}
I have test which looks like this:
#Before
public void setUp() {
adapter = new AnnotationMethodHandlerAdapter();
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
mapper = new ObjectMapper();
}
#Test
public void testAddUser() throws Exception {
request.setMethod("POST");
request.setContentType(MediaType.APPLICATION_JSON_VALUE);
request.setRequestURI("/user");
ObjectNode userJson = mapper.createObjectNode();
userJson.put("userId", "jonnybz");
userJson.put("email", "test#gmail.com");
userJson.put("password", "password");
userJson.put("longitude",-10.127205999);
userJson.put("latitude", 57.252269);
ArrayNode arrNode = mapper.createArrayNode();
arrNode.add(-10.1272059999);
arrNode.add(57.2522);
userJson.put("lonLat",arrNode);
request.setContent(mapper.writeValueAsBytes(userJson));
adapter.handle(request, response, userController);
String content = response.getContentAsString();
assertEquals(200, response.getStatus());
User user = dao.listAll().get(0);
objectId = user.getId();
assertNotNull(objectId);
}
When I execute a call against this endpoint from my client app (developed with angular) it works great, but when I run my test I get an " Content type 'application/json' which is coming from a HttpMediaTypeNotSupportedException" error that I cannot track down. The request never seems to hit my method. Am I missing something simple here?
Solved this problem by switching to the spring-mvc-test framework and building my test like this:
#Test
public void testAddUser() throws Exception {
ObjectNode userJson = mapper.createObjectNode();
userJson.put("userId", "jonnbz");
userJson.put("email", "test#gmail.com");
userJson.put("password", "password");
userJson.put("longitude",-10.667205999);
userJson.put("latitude", 74.252269);
ArrayNode arrNode = mapper.createArrayNode();
arrNode.add(-10.667205999);
arrNode.add(74.252269);
userJson.put("lonLat",arrNode);
MvcResult res = MockMvcBuilders.xmlConfigSetup("classpath:test-context.xml").build()
.perform(MockMvcRequestBuilders.post("/user")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.body(mapper.writeValueAsBytes(userJson)))
.andExpect(status().isOk())
.andExpect(content().type(MediaType.APPLICATION_JSON))
.andReturn();
System.out.println(res.getResponse().getContentAsString());
}
You should also include a Accept header of "application/json" in your test, since you have included a consumes="application/json", Spring MVC will match the Accept header value to the consumes value and only then call the mapped method.

spring mvc rest mongo dbobject response

i want to create a spring mvc rest call and the response should be the results from the mongo db (Basic)DBObject. the DBObject is, as far as i know, a JSON object. is it possible to return this objects or should i return the normal string content of them?
this is the solution i have so far:
#RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET)
public ResponseEntity<String> getContentByIdsAsJSON(#PathVariable("ids") String ids)
{
String content = null;
StringBuilder builder = new StringBuilder();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "text/html; charset=utf-8");
List<String> list = this.contentService.findContentByListingIdAsJSON(ids);
if (list.isEmpty())
{
content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><error>no data found</error>";
return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED);
}
for (String json : list)
{
builder.append(json + "\n");
}
content = builder.toString();
return new ResponseEntity<String>(content, responseHeaders, HttpStatus.CREATED);
}
does anyone have a better solution for that requirement?
thx very much in advance.
simon
I'm see a strange thing in you code. Do you must return json or xml? If you must return json it's simple in your situation, #ResponseBody do the magic
#RequestMapping(value = "/content/json/{ids}", method = RequestMethod.GET)
#ResponseBody
public MyGreatContentObject getContentByIdsAsJSON(#PathVariable("ids") String ids) {
return this.contentService.findContentByListingId(ids);
}
in any way, i'm think you still must learn base concepts a little more