Spring change the binding target - spring

I have 2 class like this :
public class A {
B b;
}
public class B {
String id;
}
I have a form that modify my object A et its subs object :
it send
b.id=XXXXX
What I want to do is
a.setB(BDao.findbyId(b.id));
I want to look up in DB for the B object and set it on my object A instead of seting the id property of the A.b object
I can do it by hand in the controller after the automatic binding:
a.setB(bDao.findbyId(a.getB().getId));
But isn't it possible to do this with a Custome editor ?
thanks !

I think it would be possible. You would have to write a custom init binder, which is basically a 'PropertyEditor', in which you can extend 'PropertyEditorSupport' class. It would look something like:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(MyClass.class, new MyCustomePropertyEditor());
}
In which your MyCustomePropertyEditor would look something like:
public class MyCustomePropertyEditorextends PropertyEditorSupport {
public void setAsText(String text) {
MyClass mc = service.doSomethingToLookUpMyClass(text);
setValue(mc);
}
}
In the JSP/View, you will need to change your tags so they set you object reference, not the reference's id. This has obviously been written off-the-cuff and by memory, so mileage might vary. You may also want to consider looking into a custom validator as well, which you can also setup through the init binder, I believe. Documentation is here.

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.

Mvc3 - Best practice to deal with data which are required for (almost) all requests?

I am creating an application in mvc3 and wondering how to deal with database data which is required for all application requests, some of them depends on a session, some of them depends on url pattern basically all data is in database.
Like to know best practice
What I do in my applications and consider to be the best practice is to load your common data to the ViewBag on the Controller constructor.
For every project, I have a DefaultController abstract class that extends Controller. So, every controller in the project must inherit from DefaultController, instead of Controller. In that class' constructor, I load all data common to the whole project, like so:
// DefaultController.cs
public abstract class DefaultController : Controller
{
protected IRepository Repo { get; private set; }
protected DefaultController(IRepository repo)
{
Repo = repo;
ViewBag.CurrentUser = GetLoggedInUser();
}
protected User GetLoggedInUser()
{
// your logic for retrieving the data here
}
}
// HomeController.cs
public class HomeController : DefaultController
{
public HomeController(IRepository repo) : base(repo)
{
}
// ... your action methods
}
That way you will always have the logged in user available in your views.
I do the same as #rdumont but with one exception: I create a CommonViewModel which I use to define all common properties that I use.
public class CommonViewModel
{
public string UserName {get;set;}
public string Extension {get;set; }
}
Declare a property in the base controller:
public abstract class BaseController : Controller
{
protected CommonViewModel Commons { get; private set; }
protected virtual void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewBag.Commons = Commons;
}
}
By doing so I get everything almost typed. The only cast that I need to do is to cast ViewBag.Commons to the CommonViewModel.
Best is to avoid ViewBag at all.
See this answer, which details how to use Html.RenderAction() for that purpose:
Best way to show account information in layout file in MVC3
I'd suggest using a base ViewModel class.
So a base class with properties/functions which should be available at any point.

Resources