Tadas Obolevicius Tadas Obolevicius - 1 month ago 8
Java Question

Java Spring REST Get works just fine, but when posting json I get 404 error

I encountered problem with Spring REST web services. When I try to post JSON I always get 404 error. Get requests works just fine, but post not. Searched all over the internet but couldn't find similar problem. Maybe you guys could help me. Here is my code:

Controller:

package com.java.rest;
import com.java.dto.IncomingTemperature;
import com.java.dto.SensorsTemperature;
import com.java.service.GetSensorsTemperature;
import com.java.service.TemperatureService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/rest")
public class TemperatureRestController {

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

@Autowired
TemperatureService temperatureService;
@Autowired
GetSensorsTemperature sensorService;

@RequestMapping(value = "/temperature", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public ResponseEntity<?> addTemperature(@RequestBody IncomingTemperature temperature){
logger.info("Temperature: {} recieved", temperature);
temperatureService.addTemperature(temperature);
return new ResponseEntity<HttpStatus>(HttpStatus.CREATED);
}

@RequestMapping(value = "/temperature/{sensorId}", method = RequestMethod.GET, produces = "application/json")
public SensorsTemperature getTemperature(@PathVariable("sensorId") Long sensorId){
logger.info("Getting temperatures for sensor{}", sensorId);
return sensorService.getSensorsTemperature(sensorId);
}


}

Model:

package com.java.dto;


import com.fasterxml.jackson.annotation.JsonFormat;

import java.io.Serializable;
import java.util.Date;

public class IncomingTemperature implements Serializable{

private long sensorId;

private double temperature;

@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
private Date date;

public long getSensorId() {
return sensorId;
}

public void setSensorId(long sensorId) {
this.sensorId = sensorId;
}

public double getTemperature() {
return temperature;
}

public void setTemperature(double temperature) {
this.temperature = temperature;
}

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}


POM.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.java</groupId>
<artifactId>knowyourheat</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>KnowYourHeat</name>
<description>Application for temperature monitoring</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.3</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>


</project>


Json that I post:

{
"sensorId" : 1,
"temperture" : 20,
"date" : "2016-10-20 22:10:10"
}


Edit:

Error that i get:

{
"timestamp": 1477601444227,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/rest/temperature/"
}


Thank you in advance!

EDIT 2:

I just created new project with the same controller, and everything works just fine. As I found out the problem is with spring security, for some reason even if I permit all requests, Post and Put method doesn't work. So that was my problem.

Answer

When using @RestController, you don't need @ResponseBody in the methods. You get 404 because the method can't accept body content of any kind. When the method only receives content from HTTP Requests, but sends no body content back, you only need consumes. ResponseEntity<xxx> defines the body content that the method will return in addition to HttpStatus. If it returns no body content and only HttpStatus, ResponseEntity<Void> must be used. Try the following

@RequestMapping(value = "/temperature", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> addTemperature(@RequestBody IncomingTemperature temperature){
    logger.info("Temperature: {} recieved", temperature);
    temperatureService.addTemperature(temperature);
    return new ResponseEntity<Void>(HttpStatus.CREATED);
}

Now you should get the HttpStatus 201 Created on client side.

Comments