Using jackson with spring mvc 2.5 - ajax

sorry for general question, but I can't google anything on that, we use spring mvc 2.5 in our project, so there is no #ResponseBody annotation, how can I make something like this without it?

You could just return it as a string built with the Jackson object mapper:
public String getCustomDetails(#PathVariable String variable1) {
CustomDetails details = new CustomDetails(variable1);
ObjectMapper mapper = new ObjectMapper();
String result = null;
result = mapper.writeValueAsString(details);
return result;
}
That should work. Might have to surround the call to writeValueAsString in a try-catch.
Edit: I should clarify that "CustomDetails" and "variable1" are just example values... they could be anything.

Related

Is it possible to customize ObjectMapper for single Spring Rest endpoint?

I know how to customize the default ObjectMapper bean. But for one specific Controller/endpoint, I'd like to use a different objectmapper. How can I do this?
I think my question is similar to this one but there are no answers yet. Happy to get an answer there and mark this as duplicate
There's a good solution by #xerx593 linked in the question's comments but I took a different approach for mine because I was returning a generic Map<String,Object> graphql return type and I didn't feel comfortable changing the media-type or applying the object mapper to all Map's. I prefer their solution for the general case as it's more elegant
I simply serialized the return object as a string and returned it.
For example, I turned something like this
#GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public Foo getFoo() {
return new Foo();
}
to something like this
private ObjectMapper customMapper = ...;
#GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public String getFoo() {
return customMapper.writeValueAsString(new Foo());
}

Populate query parameters from DTO

Is there a way to let Spring populate RestTemplate query parameters automatically from a DTO, similarly to how it instantiates the response DTO automatically?
I wish to write something like:
RequestDto request = new RequestDto();
request.setFoo("foo");
request.setBar("bar");
ResponseDto response = restTemplate.getForObject(
"http://example.com/api",
ResponseDto.class,
request
);
Instead of:
ResponseDto response = restTemplate.getForObject(
"http://example.com/api?foo={foo}&bar={bar}",
ResponseDto.class,
"foo",
"bar"
);
Because there are many large DTOs, requiring tons of boilerplate code, which must be kept in sync with any DTO changes.
Spring 4.3.25
I don't think that is directly possible. The following is not exactly using the DTO, but it does let you build the request without having to form the URL string manually. You can use Spring's UriComponentsBuilder class.
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/api")
.queryParam("foo", "bar")
// etc. ...
.queryParam("bar", "foo");
String result = restTemplate.getForObject(builder.toString(), String.class);
You could loop over the DTO and build the query as above. Or without the DTO, you could use a Map<String, String> and loop over it.
Map<String, String> params = new HashMap<>();
params.put("foo", "bar");
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://example.com/api");
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
String result = restTemplate.getForObject(builder.toString(), String.class);
Edit:
As crizzis suggested below, you can use Spring Cloud OpenFeign's REST Client (from Feign #QueryMap support):
The OpenFeign #QueryMap annotation provides support for POJOs to be used as GET parameter maps. Unfortunately, the default OpenFeign QueryMap annotation is incompatible with Spring because it lacks a value property.
and
Spring Cloud OpenFeign provides an equivalent #SpringQueryMap annotation, which is used to annotate a POJO or Map parameter as a query parameter map.
From your question's example:
public class RequestDto {
private string foo;
private string bar;
}
#FeignClient(name = "client", url = "http://example.com")
public interface FooTemplate {
#GetMapping(path = "/api")
String endpoint(#SpringQueryMap RequestDto requestDto);
}
You can do something like this-
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.com/api")
.queryParam("foo", "foo")
.queryParam("bar", "bar");
ResponseDto response = restTemplate.getForObject(
builder.buildAndExpand(builder).toUriString(),
ResponseDto.class);
A more detailed answer can be found here- RestTemplate: How to send URL and query parameters together
How about using Feign? It allows you to describe the remote endpoint just like a Spring Controller. This includes support for query parameter DTOs.
See an example here

How can I throw mapping to object exception with gson?

I'm trying to force gson to throw an exception when an string does not map to an object which I'm passing to it.
#ResponseStatus(HttpStatus.CREATED)
#PostMapping("offer")
public String postOffer(#RequestBody String jsonBody) {
Offer offer = gson.fromJson(jsonBody, Offer.class);
offerRepository.save(offer);
return offer.getId();
}
Currently, it will just save what ever it can to the db and ignore any elements that don't map to the class. This is bad for me because I get bad data making it's way to the db.
Any help would be appreciated.
ps. using springboot-data-mongodb and gson for mapping.
Thanks
In GSON you cannot make some fields required.
You can handle this i your code, if the variable is not present in json then in Offer object that variable will simple be assigned as null.
You can add null check to your code for the required fields and throw your own exception.
Since gson dont have this facility, you can also try the answer from below link-
Gson optional and required fields
To achieve this you need to follow two steps:-
1) Mark all required field in Offer class as #NotNull(message="your custom message")
2) Add below class to tell Mongo to validate document before persisting it to the database.
#Configuration
public class MongoEventValidationListener {
#Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
return new ValidatingMongoEventListener(validator());
}
#Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}

Map #CookieValue, #RequestHeader etc. to POJO in Spring Controller

I have a bunch of params in my controller and want to map all of them to a separate POJO to keep readability. There is also a #CookieValue, #RequestHeader I need to evaluate and aim for a solution to also map them to that POJO. But how?
I saw a possible solution on a blog but it doesn't work, the variable stays null.
Controller:
#RequestMapping(path = MAPPING_LANGUAGE + "/category", produces = MediaType.TEXT_HTML_VALUE)
#ResponseBody
public String category(CategoryViewResolveModel model) {
doSomething();
}
And my POJO is this:
public class CategoryViewResolveModel {
private String pageLayoutCookieValue;
public CategoryViewResolveModel() {
}
public CategoryViewResolveModel(
#CookieValue(value = "SOME_COOKIE", required = false) String pageLayoutCookieValue) {
this.pageLayoutCookieValue = pageLayoutCookieValue;
}
... some other RequestParams, PathVariables etc.
}
According to the documentation it's not possible for #CookieValue and #RequestHeader.
This annotation is supported for annotated handler methods in Servlet
and Portlet environments.
Take a look at:
https://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-creating-a-custom-handlermethodargumentresolver/
instead of using getParameter to access request parameters you can use getHeader to retrieve the header value and so define your CategoryViewResolveModel just as you were requesting

Can we pass multiple JSON objects in a REST url and capture it using Spring #RequestBody?

Is there a better way to pass multiple JSON objects and capture it in #RequestBody in Spring 3? I had referred this, but do not wish to define new wrapper classes for the purpose as explained in that question? Is it Spring's limitation or REST limitation (based on my understanding, this should not be the case)? Desperately need answer, and since I could not post additional comments in same question (was deleted), hence posting it here.
Thanks,
Paddy
for each model use #JsonIgnoreProperties(ignoreUnknown = true)
#RequestMapping(value = "/users/testBean", method = RequestMethod.POST, consumes={"application/json","application/xml"}, produces={"application/json","application/xml"})
public #ResponseBody List<User> testBean(#RequestBody Object object) {
System.out.println("testBean called");
System.out.println(object.toString());
ObjectMapper mapper=new ObjectMapper();
User user =mapper.convertValue(object, User.class);
Tree tree =mapper.convertValue(object, Tree.class);
System.out.println("User:"+user.toString());
System.out.println("Tree:"+tree.toString());
return userService.findAll();
}

Resources