Thread safe on Inheritance of spring boot controller - spring-boot

I am writing an API using Spring Boot, and I have a abstract controller to hold the shared logic among several controllers. Now I want to add a warning field:
public abstract class BaseController<T> {
public List<String> warnings;
#RequestMapping(method = POST)
public Response create(HttpServletRequest request,HttpServletResponse response) {
warnings = new ArrayList<>();
if (something bad from T) {
warning.add("bad thing happens");
}
return createRespone(warnings);
}
(createReponse is uesd to create custom reponse)
And I have several different controller inherited from it
#RestController
#RequestMapping("/{area}/blah")
public class BlahController extends BaseController<Blah> {
}
For the warning field, will it be shared several different children controller, or will only one instance alive? If controller A and controller B are both inherited from BaseController and tried to modify warning, is it thread safe?

The warning field is not shared. Your code is equivalent to:
BaseController<blah> blahController = new BlahController();
BaseController<noh> nohController = new NohController();
Having state in a controller is against the REST concepts.

Related

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.

Jaxb setting dynamic #XmlRootElement with Spring Web Services

I have a Spring application that consumes a SOAP web services. I have several classes that are quite simple and only differ in the #XmlRootElement. I'm wondering if there's a way to create a more generic class that I can set the root element on dymanically.
Here's a few of the classes with only the root element being different.
#XmlRootElement(name="safetydate")
public class SafetyDateRequest extends Carrier411RequestImpl {
}
#XmlRootElement(name="checkallsafety")
public class SafetyGetAllRequest extends Carrier411RequestImpl {
}
#XmlRootElement(name="checksafetyupdates")
public class SafetyGetUpdatesRequest extends Carrier411RequestImpl {
}
In another class, I'm processing these classes in the following fashion:
private void sendRequest(Carrier411Request request, Carrier411ResponseHandler responseHandler) throws FaultCodeException {
Carrier411Response response = (Carrier411Response) ws.marshalSendAndReceive(registry.get(request.getClass()), request);
checkResponseForFault(response);
responseHandler.handleResponse(request, response);
}
I know there's another version of marshalSendAndReceive that accepts a callback allowing you to modify the request before actually sending it, but I haven't figured out how to achieve what I'm trying to do.

Best practice to access and display data from DB that is common across all pages

I have a webstore with a bunch of Spring MVC controllers defined for each JSP page such as HomePageController, CategoryPageController, ProductPageController, CartPageController etc. and all these controllers makes a call to the DB to fetch and display the menu on top of JSP pages. Each of the controllers mentioned above makes a call to the DB in order to fetch the menu.
I am using Spring 3.0 framework.
HomePageController.java
#Controller
#RequestMapping(HOME_PAGE_CONTROLLER)
public class HomePageController extends BasePageController {
#RequestMapping(method = RequestMethod.GET)
protected ModelAndView processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ModelAndView mav = new ModelAndView();
mav.addObject("menuCategories", masterDataService.getAllMenuCategories());
return showPage(mav, HOME_PAGE_URL);
}
}
I kind of feel that this call is redundant because
1) all the controllers are making this call to build the menu
2) difficult to maintain because change in business logic will require changes in multiple controllers
What is the best practice in this type of scenario? How can I avoid this call getting make from multiple controllers? Is there a way to make this call at a central location so that this piece of code does not cut across all the controllers?
Avoid duplicating code across controller classes - If all controller classes extend BasePageController:
public abstract class BasePageController {
...
#ModelAttribute
public void initMenuCategories(Model model) {
model.addAttribute("menuCategories", masterDataService.getAllMenuCategories());
}
...
}
Reduce database calls per page - Consider caching the menu categories if they don't change too often:
#Service
public class MasterDataService {
...
#Cacheable(key = "menu", value = "menu")
public List<MenuCategory> getAllMenuCategories() { ... }
...
}
You will have to add a cache named menu to your service layer configuration for this to work. See the documentation on Caching with Spring for details.

How to apply a global filter in playframework

When using #before, it is only used in one class. How do I apply a global filter in playframework? So that one filter is used for all controller classes.
A simple solution is to extend a base controller for all of your controllers and have the #Before in the base controller.
The other option (and the better solution, as it is more flexible) is to use the #With annotation. The example on the play documentation is
Example:
public class Secure extends Controller {
#Before
static void checkAuthenticated() {
if(!session.containsKey("user")) {
unAuthorized();
}
}
}
And on another Controller:
#With(Secure.class)
public class Admin extends Application {
...
}
This means the Admin controller will process all the interceptors (#Before, #After, #Finally) contained within the Secure controller.
I did this very thing by handling incoming requests globally in the GlobalSettings class:
This describes the class:
http://www.playframework.org/documentation/2.0/JavaGlobal
This describes the method you'd want to override.
http://www.playframework.org/documentation/2.0/JavaInterceptors
Here's an example of how I used it in my own project (of course, this is a simplified version of what you're looking for):
#Override
public play.mvc.Action onRequest(play.mvc.Http.Request request, java.lang.reflect.Method method) {
if (request.path().startsWith("/secret/locked")) {
return new Action.Simple() {
#Override
public Result call(play.mvc.Http.Context ctx) throws Throwable {
return redirect(routes.Application.forbidden());
}
};
}
return super.onRequest(request, method);
}
You can simply use PlayPlugin for this issue. See here for more details.
It's not a good solution to extend a base controller for all of your controllers and have the #Before in the base controller.
You can extends the filter or essensialfilter .e.g.
class filter1 extends Filter {}
and apply filter1 to Global

Resources