How to architect/annotate beans so they come from session after 1st time creation from persistence layer - spring

I am early in the architecting phase of a project -- there is no code to post. Basically, I have a controller retrieving a "Model bean" which roughly corresponds to the page/form: so it has form information (what checkboxes are selected, etc.) -- and also contains domain beans (database entity info).
How to get Spring to create "default" info for the "model beans" on the first use, but retrieve from session thereafter. And similarly, how to get Spring to create domain bean from persistence layer 1st time, but retrieve it from the session thereafter? EDIT: Using just annotations.

If I got your question right. This is what I have done.
Under LoginController I have condition to authenticate user. Then I add the user info in a bean and redirectAttrs.addFlashAttribute("mySession", thisIsUserSessionBean);
This is redirected to another controller called LandingController. Annotation under LandingController is something like below. Note: #SesssionAttributes annotation. You can add any information under this session object. My suggestion, keep the bean smaller for performance sake.
#Controller
#RequestMapping(value = "/homepage")
#SessionAttributes({"mySession"})
public class LandingController
I would not prefer to have domain bean sticked in session.

Related

How to avoid the vulnerability created by using entities at a requestMapping method?

I have a controller with a method like
#PostMapping(value="/{reader}")
public String addToReadingList(#PathVariable("reader") String reader, Book book) {
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/readingList/{reader}";
}
When I run a static code analysis with Sonarqube I get a vulnerability report stating that
Replace this persistent entity with a simple POJO or DTO object
But if I use a DTO (which has exactly the same fields as the entity class, then I get another error:
1 duplicated blocks of code must be removed
What should be the right solution?
Thanks in advance.
Enric
You should build a new separate class which represents your Entity ("Book" ) as Plain Old Java Object (POJO) or Data Transfer Object (DTO). If you use JSF or other stateful technology this rule is important. If your entity is stateful there might be open JPA sessions etc. which may modify your database (e.g. if you call a setter in JSF on a stateful bean).
For my projects I ignore this Sonar rule because of two reasons:
I alway you REST and REST will map my Java Class into JSON which can be seen as a DTO.
REST is stateless (no server session) so no database transaction will be open after the transformation to JSON
Information obtained from sonarsource official documentation.
On one side, Spring MVC automatically bind request parameters to beans
declared as arguments of methods annotated with #RequestMapping.
Because of this automatic binding feature, it’s possible to feed some
unexpected fields on the arguments of the #RequestMapping annotated
methods.
On the other end, persistent objects (#Entity or #Document) are linked
to the underlying database and updated automatically by a persistence
framework, such as Hibernate, JPA or Spring Data MongoDB.
These two facts combined together can lead to malicious attack: if a
persistent object is used as an argument of a method annotated with
#RequestMapping, it’s possible from a specially crafted user input, to
change the content of unexpected fields into the database.
For this reason, using #Entity or #Document objects as arguments of
methods annotated with #RequestMapping should be avoided.
In addition to #RequestMapping, this rule also considers the
annotations introduced in Spring Framework 4.3: #GetMapping,
#PostMapping, #PutMapping, #DeleteMapping, #PatchMapping.
See More Here

getting bean id of target class in advice

I have a few classes that interact with databases (more than one). Some classes are reused so for example "obs.table1" is used to interact with table1 in database "obs" while "ref.table1" is used to interact with table1 in database "ref". These databases are at different URLs and each gets its own connection pool, etc... obs.table1 and ref.table1 are both instances of MyTable1Class, defined in beans file.
I have a pointcut that intercepts calls to methods annotated with #Transactional or with a custom annotation #MyTablesAnnotation and have it set so those calls will all get routed into a #Around advice.
This all works and the flow through the advice is correct.
What I am trying to add is reporting on what is going on in there. Currently I can tell where in there I am, but I can't tell if it was obs.table1 or ref.table1 object that got me there.
Is there a way to extract the bean id of the object on whose method the advice was invoked on?
ProceedingJoinPoint that is passed to the method the only thing I do with it is call a .proceed on it and the rest is just various checks and catches. I see that I can get either the target class or proxy class out of it, but... not sure how to go from there to knowing what the bean id was.
Is it possible?
Firstly it is not recommended to depend on bean id as it creates tight coupling with framework.
To quote from docs Note that it is not usually recommended that an object depend on its bean name, as this represents a potentially brittle dependence on external configuration, as well as a possibly unnecessary dependence on a Spring API.
Now to answer your question yes it is possible to fetch the name of bean via org.springframework.beans.factory.BeanNameAware.
The class for which you require the bean name should implement it and spring will auto-magically inject the name of the bean. However there is a gotcha which you should be aware and is mentioned in docs here

Spring: new() operator and autowired together

If I use Spring, which of these two methods is more correct.
Can I use the new() operator even if I use dipendency injection?.Can I mix both?
I would like to have some clarification on these concepts.
Thanks
First method:
#RequestMapping(method=RequestMethod.GET)
public String create(Model model){
model.addAttribute(new User());
return "index";
}
Second Method:
#Autowired
User user;
#RequestMapping(method=RequestMethod.GET)
public String create(Model model){
model.addAttribute(user);
return "index";
}
By using dependency injection does not mean that the use of new operator is automatically prohibited throughout your code. It's just different approaches applied to different requirements.
A web application in spring is composed of a number of collaborating beans that are instantiated by the framework and (unless overriding the default scope) are singletons. This means that they must not preserve any state since they are shared across all requests (threads). In other words if you autowire the User object (or any other model attribute), it is created on application context initialization and the same instance is given to any user request. This also means that if a request modifies the object, other requests will see the modification as well. Needless to say this is erroneous behavior in multithreaded applications because your User object (or other model attribute) belongs to the request, so it must have the very narrow scope of a method invocation, or session at most.
You can also have spring create beans with different scopes for you, but for a simple scenario of a model attribute initialization, the new operator is sufficient. See the following documentation if interested in bean scopes : Bean scopes
So in your use case, the second method is totally wrong.
But you can also delegate the creation of your model attributes to spring if they are used as command objects (i.e. if you want to bind request parameters to them). Just add it in the method signature (with or without the modelattribute annotation).
So you may also write the above code as
#RequestMapping(method=RequestMethod.GET)
public String create(#ModelAttribute User user){
return "index";
}
see also : Supported method argument types
If you want your beans to be "managed" by Spring (for e.g. to use with Dependency Injection or PropertySources or any other Spring-related functionality), then you do NOT create new objects on your own. You declare them (via XML or JavaConfig) and let Spring create and manage them.
If the beans don't need to be "managed" by Spring, you can create a new instance using new operator.
In your case, is this particular object - User - used anywhere else in code? Is it being injected into any other Spring bean? Or is any other Spring bean being injected in User? How about any other Spring-based functionality?
If the answer to all these questions is "No", then you can use the first method (create a new object and return it). As soon as the create() method execution is complete, the User object created there would go out of scope and will be marked for GC. The User object created in this method will eventually be GC-ed.
Things can be injected in two ways in a Spring MVC applications. And yes, you can you can mix injection and creation if doing right.
Components like the controller in your example are singletons managed by the application context. If you inject anything to them it is global, not per request or session! So a user is not the right thing to inject, a user directory can be. Be aware of this as you are writing a multithreaded application!
Request related things can be injected to the method like the used locale, the request, the user principal may be injected as parameters, see a full list at Spring MVC Documentation.
But if you create a model attribute you may use new() to create it from scratch. I will not be filled by spring but to be used by your view to display data created by the controller. When created in the request mapped method that is ok.

jsf 2 spring application logging specific events

I have an JSF2 app which uses Spring for transactions,security and DI container.
The application has 3 layers :
1. JSF view + JSF Managed Bean
2. Service classes
3. DAO classes
So, a request is something like:
JSF Page -> JSF MB -> Service class -> DAO Class -> DB, and the the other way around.
My problem is that there are service methods that after perform their business had to log to DB that event.
For instance, when someone activates/deactivates a user. I want to log this action along with the user id.
So, I only see two approaches here : (I`m sure there are more)
1. inside this method I determine the logged in user and perform the actual logging
- as i disadvantages here I would see the fact that this method will be not so easy to test, because of the userId picked from SpringSecurity
2. Using SpringAOP. This way would be noninvasive, which is cool, but then I would have an aspect for one method, which is not so efficient.
I would like to know if you guys had this kind of issues and if so, how did you solve them ?
Consider introducing a marker annotation. Let's call it: #LogEvent. Then annotate every method you wish to intercept. This way you can implement a single aspect with an advice that matches not on naming convention but on the presence of #LogEvent.
something like:
#After("execution(#LogEvent * *.*(..))")

Recording the user session on JBoss and returning different views based on the session

I have a JSF function which returns different views depending on certain information stored on the user currently viewing/manipulating the page. I.e. depending if the customer has a gold/silver/bronze subscription, the view will display different amounts of information. Is there a JBoss way to do this simply? I read something about SessionBean but I am not sure as to how to implement it, or even if the Bean will contain the data that I need.
BTW I am on JBoss 7.1 with JPA 2 and Java EE 6
WHat about this solution.
-you can create 3 separate beans for each subscription type and have all the rendering logic in their eg:
SilverBean
GoldBean
BronzeBean
and then have a central bean called: SomeBean. Now what you can do is inject the three beans in the SomeBean.
You can then have a Map and then store the beans linking to the subscribtion type.
When the user loggs in you can then search for their subscription type and then render the view with the requried bean.
HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
gets the name of the person currently logged in!

Resources