Reputation: 29537
I have an SSCCE that reproduces this problem exactly at my GitHub repo here. To run it locally just:
./gradlew clean build
java -Dspring.config=. -jar build/libs/bootup.jar
http://localhost:9200/cars/1
Essentially I have a Spring Boot app (written in Groovy) that has a single CarController
:
@Slf4j
@RestController
@RequestMapping(value = "/cars")
class CarController {
// Mock for an actual DB
static Map<Long,Car> carDb
static {
carDb = new HashMap<Long,Car>()
carDb.put(1, new Car(
1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
"Toyota", "Corolla")
)
carDb.put(2, new Car(
2, UUID.fromString("45a148b9-a44b-41c2-8ad4-c3b5069f091a"),
new CarType(11, UUID.fromString("b68148b9-a44b-41c2-8ad4-c3b5069f0922"), "Sport Utility Vehicle", "SUV"),
"Honda", "CRV")
)
carDb.put(3, new Car(
3, UUID.fromString("fe9ede26-886a-4bd9-9b09-535387fffe88"),
new CarType(12, UUID.fromString("5a5ede26-886a-4bd9-9b09-535387fffe10"), "Truck", "TRUCK"),
"Chevy", "Silverado")
)
}
@RequestMapping(value = "/{carId}", method = RequestMethod.GET)
Car getCarById(@PathVariable(value = "carId") Long carId) {
carDb.get(carId)
}
@RequestMapping(method = RequestMethod.POST)
void createCar(@RequestBody Car car) {
log.info("Received a car: ${car}")
}
}
Where Car
and CarType
, respectively are:
@Canonical
abstract class BaseEntity {
Long id
UUID refId
}
@Canonical
@TupleConstructor(includeSuperProperties = true)
@ToString(includeSuperProperties = true)
class Car extends BaseEntity {
CarType type
String make
String model
}
@Canonical
@TupleConstructor(includeSuperProperties = true)
@ToString(includeSuperProperties = true)
class CarType extends BaseEntity {
String name
String label
}
I'm using Spring Boot Actuator and here are the dependencies I'm pulling in:
compile(
'org.codehaus.groovy:groovy-all:2.4.6'
,'org.springframework.boot:spring-boot-starter-actuator'
,'org.springframework.boot:spring-boot-starter-jetty'
//,'org.springframework.boot:spring-boot-starter-security'
// ,'org.springframework.boot:spring-boot-starter-thymeleaf'
,'org.apache.commons:commons-lang3:3.4'
,'ch.qos.logback:logback-parent:1.1.7'
)
compile('org.springframework.boot:spring-boot-starter-web') {
exclude module: 'spring-boot-starter-tomcat'
}
dev('org.springframework.boot:spring-boot-devtools')
When I run this (using the steps mentioned above) it starts up just fine. I then open my browser to http://localhost:9200/cars/1
(hoping to get back the first Car
in the carDb
as a JSON payload) but nothing is returned. In the logs, when I search for that request I see:
2017-04-08 05:06:58.668 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/cars/1]
2017-04-08 05:06:58.675 DEBUG 31573 --- [tp1164253047-17] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /cars/1
2017-04-08 05:06:58.678 DEBUG 31573 --- [tp1164253047-17] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public hotmeatballsoup.bootup.model.Car hotmeatballsoup.bootup.controllers.CarController.getCarById(java.lang.Long)]
2017-04-08 05:06:58.678 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/cars/1] is: -1
2017-04-08 05:06:58.751 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-04-08 05:06:58.751 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet : Successfully completed request
2017-04-08 05:06:58.774 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/favicon.ico]
2017-04-08 05:06:58.774 DEBUG 31573 --- [tp1164253047-21] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/favicon.ico] are [/**/favicon.ico]
2017-04-08 05:06:58.775 DEBUG 31573 --- [tp1164253047-21] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/favicon.ico] are {}
2017-04-08 05:06:58.775 DEBUG 31573 --- [tp1164253047-21] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/favicon.ico] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@592dfeae]]] and 1 interceptor
2017-04-08 05:06:58.776 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/favicon.ico] is: -1
2017-04-08 05:06:58.781 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-04-08 05:06:58.781 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet : Successfully completed request
I'm not sure how to interpret those logs, but I feel like Spring Boot is trying to treat this like a request for HTML (web page) data, not JSON-based REST data.
So I ask: What do I need to do so that a GET request to http://localhost:9200/cars/1
returns JSON, perhaps something like:
{
"id" : 1,
"refId" : "d3bdc4ea-4c62-4bd2-a751-681a531f34f4",
"type" : {
"id" : 10,
"refId" : "ba4dc4ea-4c62-4bd2-a751-681a531f3487",
"name" : "Sedan",
"label" : "SEDAN"
}
"make" : "Toyota",
"model" : "Corolla"
}
Any ideas?
Upvotes: 3
Views: 1394
Reputation: 11470
The problem is your map. You define it as <Long,Car>
but when adding the initial data you use Integer
for your cars:
carDb.put(1, new Car(
1L, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
"Toyota", "Corolla")
)
So if you ask your map if the key 1L (Long) is part of the map you get nothing. However 1 (as Integer) is part of your map and would return a Car. Since your get
method gets a Long value but all your keys are Integers you never find a car in your HashMap. You need to initialise your map with long values like this:
static {
carDb = new HashMap<Long,Car>()
carDb.put(1L, new Car(
1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
"Toyota", "Corolla")
)
carDb.put(2L, new Car(
2, UUID.fromString("45a148b9-a44b-41c2-8ad4-c3b5069f091a"),
new CarType(11, UUID.fromString("b68148b9-a44b-41c2-8ad4-c3b5069f0922"), "Sport Utility Vehicle", "SUV"),
"Honda", "CRV")
)
carDb.put(3L, new Car(
3, UUID.fromString("fe9ede26-886a-4bd9-9b09-535387fffe88"),
new CarType(12, UUID.fromString("5a5ede26-886a-4bd9-9b09-535387fffe10"), "Truck", "TRUCK"),
"Chevy", "Silverado")
)
}
Upvotes: 1
Reputation: 1153
The problem is car.get(carId )
is returning null. try the following
@RequestMapping(value = "/{carId}", method = RequestMethod.GET)
Car getCarById(@PathVariable(value = "carId") Long carId) {
println 'car >> ' + carDb.get(carId)
return new Car(
1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
"Toyota", "Corolla")
}
initalize your map like this and your original code will work
static Map<Long,Car> carDb = [(1l): new Car(
1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
"Toyota", "Corolla"),
(2l): new Car(
2, UUID.fromString("45a148b9-a44b-41c2-8ad4-c3b5069f091a"),
new CarType(11, UUID.fromString("b68148b9-a44b-41c2-8ad4-c3b5069f0922"), "Sport Utility Vehicle", "SUV"),
"Honda", "CRV"),
(3l): new Car(
3, UUID.fromString("fe9ede26-886a-4bd9-9b09-535387fffe88"),
new CarType(12, UUID.fromString("5a5ede26-886a-4bd9-9b09-535387fffe10"), "Truck", "TRUCK"),
"Chevy", "Silverado")
]
Upvotes: 4
Reputation: 9536
Your controller method is not returning anything
@RequestMapping(value = "/{carId}", method = RequestMethod.GET)
Car getCarById(@PathVariable(value = "carId") Long carId) {
carDb.get(carId)
}
This method would not even compil,e as you specified it to return a Car, but do not return anything. May be you posted the wrong code, or the method you are using looks different. What you need to do, is return an instance of Car there, than it should work.
Upvotes: 1