Spring's #RequestParam with Nested Objects / Rich Model Objects - spring

Simple problem:
#Controller
class MyController {
#RequestMapping(...)
void test(MyModel m) {
...
}
}
class MyModel {
MyNestedModel a;
}
class MyNestedModel {
#RequestParam("b[]")
List<String> b;
}
This apperantly does not work, because #RequestParam only works with method parameters.
Is there a way to define the name of the request param within the model object?
Reason:
My MyModel and MyNestedModel classes is of course much bigger and I'd like to use for example ?a.b[]=TEST.
Thanks for your help :)
EDIT: Looks like this is exactly my problem: How to customize parameter names when binding spring mvc command objects

Spring mvc can transfer the parameter for you. But the post data should be like:
{a.b[0] : "b1", a.b[1] : "b2"}
then you can get a list in m.a.b

Related

Spring form ModelAttribute List binding

There are way to bind List object by using spring modelAttribute?
Actually, I know that it can be done by using Wrapper class having list member variable.
like this
Dto :
public class SampleDto {
private List<SubSampleDto> sampleList;
}
Controller :
#RequestMapping(value = "/sample/insert.ajax")
public String set(#ModelAttribute("sampleDto") SampleDto dto) {
...
}
But, I want to know the way not to use wrapper class.
Thanks
You could bind it like,
#ModelAttribute("sampleList")
public List<SubSampleDto> getAll() {
return subSampleDtoService.getAll(); //or something to get SubSampleDto list
}
if i understood you correctly

How can I put an instance of an object as session attribute in a Spring MVC project?

I am working on a Spring MVC application and I have the following problem.
I have this RegistrazioneInfo class that contains some information inserted into a form by the user:
public class RegistrazioneInfo {
#NotNull
#Size(min=16, max=16)
private String codiceFiscale;
String gRecaptchaResponse;
public String getCodiceFiscale() {
return codiceFiscale;
}
public void setCodiceFiscale(String codiceFiscale) {
this.codiceFiscale = codiceFiscale;
}
public String getgRecaptchaResponse() {
return gRecaptchaResponse;
}
public void setgRecaptchaResponse(String gRecaptchaResponse) {
this.gRecaptchaResponse = gRecaptchaResponse;
}
}
Then I have this controller class:
#Controller
public class RegistrazioneController extends BaseController {
private RegistrazioneInfo registrazioneInfo;
...............................................
...............................................
...............................................
}
that contains some methods handling request towards some resources.
Ok, my problem is that I want to use an instance of the previous RegistrazioneInfo class as session attribute by the use of the #SessionAttributes Spring annotation as shown here: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-sessionattrib
My problem is, in the previous example do something like this:
#SessionAttributes("pet")
public class EditPetForm {
// ...
}
So what exactly is pet? I think that it is something like an id that identify the object that have to be used as a session attribute or something like this. How can I say to put an instance of my RegistrazioneInfo as session attribute?
#SessionAttributes is declared in a Controller Class (#Controller), so on the class level.
Pet is an Bean Object that persist in HttpSession
From the documentation:
This will typically list the names of model attributes which should be transparently stored in the session or some conversational storage, serving as form-backing beans. Declared at the type level, applying to the model attributes that the annotated handler class operates on.
(emphasis is mine)
Also note that, as indicated in the documentation, you should not use that for "non temporary" elements.

Can I "inject" values from message resources into model objects before implicit Jackson serialisation?

I have a REST API built with Spring Boot / Spring MVC, using the implicit JSON serialization via Jackson.
Now, just before the implicit serialization, I would like to "inject" some UI texts from message resources into the objects that Jackson converts into JSON. Is there some neat, simple way to do this?
As a much simplified example, below I'd like to set Section title to a user-visible value, based purely based on its SectionType.
(Sure, I could hardcode the UI texts in SectionType, but I'd rather keep them separate, in resource files, because it's cleaner, and they might be localised at some point. And I can't autowire MessageSource in the entities / model objects which are not Spring-managed.)
#Entity
public class Entry {
// persistent fields omitted
#JsonProperty
public List<Sections> getSections() {
// Sections created on-the-fly, based on persistent data
}
}
public class Section {
public SectionType type;
public String title; // user-readable text whose value only depends on type
}
public enum SectionType {
MAIN,
FOO,
BAR;
public String getUiTextKey() {
return String.format("section.%s", name());
}
}
Somewhere in a #RestController:
#RequestMapping(value = "/entry/{id}", method = RequestMethod.GET)
public Entry entry(#PathVariable("id") Long id) {
return service.findEntry(id);
}
UI texts that I'd like to keep separate from code (messages_en.properties):
section.MAIN=Main Section
section.FOO=Proper UI text for the FOO section
section.BAR=This might get localised one day, you know
And what I'd like to do in a Spring-managed service/bean somewhere (using Messages, a very simple helper wrapping a MessageSource):
section.title = messages.get(section.type.getUiTextKey())
Note that if I call entry.getSections() and set the title for each, it will not affect the JSON output, since the Sections are generated on the fly in getSections().
Do I have to go all the way to custom deseriazation, or is there a simpler way to hook into the model objects just before they get serialized by Jackson?
Sorry if the question is unclear; I can try to clarify if needed.
As I said in the comment you can write an Aspect around every controller method that returns Section.
I wrote a simple example. You have to modify it with the message source.
Controller:
#RestController
#RequestMapping("/home")
public class HomeController {
#RequestMapping("/index")
public Person index(){
Person person = new Person();
person.setName("evgeni");
return person;
}
}
Aspect
#Aspect
#Component
public class MyAspect {
#Around("execution(public Person com.example..*Controller.*(..))")//you can play with the pointcut here
public Object addSectionMessage(ProceedingJoinPoint pjp) throws Throwable {
Object retVal = pjp.proceed();
Person p = (Person) retVal; // here cast to your class(Section) instead of Person
p.setAge(26);//modify the object as you wish and return it
return p;
}
}
Since the aspect is also a #Component you can #Autowire in it.

WebApi Controller action parameter base class for common features

Where WebApi Controller actions share identical features, E.g. pagination and partial response, is it possible to create a base class to model these parameters?
For example, this URI:
http://letsdoitclean.com/api/v1/athletes?clean=true&fields=name,age&offset=0&limit=25
might map to:
class AthletesController
{
IHttp Get(bool clean, string[] fields, int offset, int limit)
{
...
}
}
However, fields, offset and limit are concepts that will be frequently used. So I want something like:
abstract class ActionParameter
{
public string[] fields;
public int offset;
public int limit;
}
class AthletesGetParameter : ActionParameter
{
public bool clean;
}
class AthletesController
{
IHttp Get(AthletesGetParameter param)
{
...
}
}
Can I do it?
This could also be achieved by adding it globally to your WebApiConfig so that you don't have to mark it up in every single controller action:
config.ParameterBindingRules.Insert(0, descriptor =>
typeof(ActionParameter).IsAssignableFrom(descriptor.ParameterType)
? new FromUriAttribute().GetBinding(descriptor)
: null);
Yes, absolutely you can do this. ASP.NET will handle the parameter binding if you, in this example, specify the FromUriAttribute for the complex object:
public class AthletesController : ApiController
{
public string Get([FromUri] AthletesGetParameter athletesGetParam)
{
// ...
}
}
The only thing I would argue against from your question, is the name of the abstract class. It doesn't really describe the base class all that well and what it's intended for. Maybe something like abstract class PaginationParameter or something similar. To call it ActionParameter could confuse you in the future (or other programmers) that all action parameters should derive this class, and I don't think that's right.
Maybe minutia on the naming of the base class, but to answer your direct question... yes you can do this.

Generic Request Param (runtime construction)

My requests look like:
http://...
?type[A].size=14
&type[B].query=test
My #Controller has a method which should accept those generic request params:
#RequestMapping(...)
public void test(MyModel m) {
...
}
public static class MyModel {
Map<String, ?> type;
}
The problem is: ? should be some class which is defined by the key of the Map.
This means: key=A should Map to class A and key=B should map to class B. According to the given request above: Class A will have a property int size and class B will have a property String query.
I just can't figure out, how I can tell Spring to use class A for key A and class B for key B.
(I know I could do it with POST and Jackson, but I'd like to solve this using a GET request).
Thanks for your help :)

Resources