Do I really need to learn all controller classess? - spring

I started learning spring MVC And in controller there is list of 14 classes below:
SimpleFormController
AbstractController
AbstractCommandController
CancellableFormController
AbstractCommandController
MultiActionController
ParameterizableViewController
ServletForwardingController
ServletWrappingController
UrlFilenameViewController
AbstractController
AbstractCommandController
SimpleFormController
CancellableFormController
Do I really need to go through all of them? or #Controller (i.e.MultiActionController) is sufficient?
I think all these classes belongs to very old versions of Spring framework and now a days we don't need to learn them. Need Guidance.

I've gotten by with just #Controller on my Spring Boot projects.
I can't think of a case where you need to worry about which class is auto-wired by the annotation, unless you need to write your own implementation for a specific application flow which uses that specific controller. And, again, I've never had to do this. I only have 1 year of experience with Spring in production, however, so keep that in mind.

Related

Injecting spring beans into legacy web app POJOs [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
In order to provide POJOs in my legacy web app (Tomcat 8.0.26) with the ability to send ActiveMQ messages I've taken the recommendation to introduce Camel (2.15.2) / Spring (4.2.1) into the app to purely for the purpose of managing pooled MQ connections. I'm hoping there isn't an easier way.
Doing things the Spring way I'm thinking everything would need to be based around an MVC architecture with HTTP servlet aware controllers having access to the servlet context and therefore the Spring context in order to inject beanFactory beans into classes annotated with #Controller and #Service (and in fact there must be a Spring #Controller class that enables Spring to inject the #Service class.
However, as I've stated this is legacy code that will not be using the spring web framework.
After much pain it seems that the only way I can get beanFactory beans injected into my POJOs is to go the AspectJ and Weaving route. Before I go down this road can someone tell me that this is currently the best approach (what I've read describing this solution is from 2011 Can't get Spring to inject my dependencies - Spring Newbie) ? Can you point me to documentation and a working example?
Many thanks.
1) aspectj with #Configurable
In your #Configuration annotated class/es
you can add some more annotations
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableSpringConfigured
#EnableAspectJAutoProxy
to enable aspectj and the #Configurable annotation,
you need to import the aspectj lib to your project and add the spring tomcat instrumentable java agent in your tomcat lib folder (give a look here, it exaplains how to configure tomcat) http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/instrument/classloading/tomcat/TomcatInstrumentableClassLoader.html
this is not going to help you if you are going to create your pojos using "new"
MyPojo p = new MyPojo(); // no black magic for this, you will need to satisfies the dependencies yourself) but that would be helpful for example when you load some entities through a framework like hibernate and you want to inject something into them.. #Configurable it's an option that can be evaluated in those cases, for what you describe I would rather not use it.
2) You can have some static methods that uses some static set spring-beans and use them from your pojos, something like
class Util{
private static SprintBeanWithJmsSupport x;
public static setSpringBeanToHandleJmsMessages(SprintBeanWithJmsSupport x){
Util.x = x;
}
public static sendJmsMessage(JmsMessage m){
x.sendMessage(m)
}
}
and you can go with Util.sendJmsMessage(...)
this is a bit shitty but it does the work, I don't personally like this approach
3) set your spring beans in your pojo when they need to use them (maybe behind some nice interfaces that suit your domain)
if you go with spring mvc you will likely end up having some controllers that will use some services (generally they handle security / db access and are the entry point to start the "use cases"), as everything wthin these layers is handled by spring it will be very simple to pass the spring-bean to handle jms messaging to your pojos, this seems to me quite a nice way to handle the problem
I went mostly based on memory and something may not be completely accurate, plus my english is .. what it is, so hope this can be helpful anyway.

Using Inheritance in Spring MVC 3.1

Researching the use of inheritance in Spring MVC.
Is it a good idea to have a base controller that other controllers can extend ?
The base controller would be to hold functionality common to all controllers.For E-g getting a handle to the logged-in user etc.
If using the base controller is not a good idea are there any other suggestions to implement something like what I have mentioned above.
It is perfectly acceptable to have a base controller that other controllers can extend. When Spring introduced #Controller annotations, they paved the way for you to use whatever class hierarchy you want.
Just be aware that as an object oriented design principle, it's good to favor composition over inheritance. As a rule of thumb (not a hard and fast rule) I would recommend moving your common controller code into a class whose interface can be injected into your controllers via #Inject or #Autowired.
Another suggestion for getting a handle to the logged-in user is a little more work but very nice once you have it. See the discussion here about using a current user annotation on your controller method arguments. This is what I do on my project and it works great!

How to add a custom annotation to Spring MVC?

Can anyone explain what I need to do to implement my own annotation that would add functionality to my web requests?
For example:
#Controller
public class MyController {
#RequestMapping("/abc")
#RequiresSomeSpecialHandling
public void handleSecureRequest() {
}
}
Here #RequiresSomeSpecialHandling would be my own annotation that causes some special work to be done before or after the given web request /abc.
I know that on a very high level I would need to write a bean post processor, scan classes for my annotations, and inject custom mvc interceptors when needed. But are there any shortcuts to simplify this task? Especially for the two examples above.
Thanks in advance,
This kind of Annotations, (that add additional functionality when invoking a method) looks like annotations that trigger an AOP Advice.
#see Spring Reference Chapter 7. Aspect Oriented Programming with Spring
The idea is to use the Annotation to trigger the AOP Advice.
like:
#Pointcut("#target(com.example.RequiresAuth)")
Depends on what you want to do as a result of #RequiresSomeSpecialHandling. E.g. do you want it to influence request mappings or the invocation of the method (i.e. resolving method arguments, processing the return value)?
The support for annotated classes in Spring 3.1 became much more customizable. You can browse some examples in this repo.
Also keep in mind that a HandlerInterceptor in Spring 3.1 can cast the handler Object to HandlerMethod, which gives you access to the exact method including its annotations. That may be enough for what you need to do.
If caching is one of your goals, take a look at the #Cacheable annotation (and its siblings #CachePut, #CacheEvict and #Caching), available as of Spring 3.1.

JSF2 managed bean annotation + scope + injection confusion

I would like to achieve this idealism :
To have only 1 implementation for the JSF Bean container, like to use only Spring or Weld but not both. Currently i am using Spring for my backend, so i prefer Spring.
To have only 1 annotation, to choose between #ManagedBean, #Named, #Model
To be able to use all supported scopes, like #RequestScoped, #SessionScoped, #ViewScoped, #FlashScoped, maybe also #ConversationScoped
The JSF Beans could be injected with spring-managed-services (The backend services), perhaps using #Inject or #Autowired
So far i've been finding no best combination to achieve these because as far as i know, please correct me if i am wrong, :
#ManagedBean can not be injected with spring services ?
#Named can be injected with spring services using #Inject, but #Named is using Weld. Can i just use spring to managed the #Named instead of Weld ?
#Named doesnt support #ViewScoped and FlashScope ?
Please share your thoughts and experiences.
Thank you :-)
UPDATE 15 March 2011
Found an interesting page that describes how to replace Jboss Weld with Spring as the JSR 299 CDI implementation. So basically, the question number 2 is answered. Number 1 is also answered indirectly since i can now inject spring services.
But still, the number 3 question remains. I would find very helpful if i can use the #ViewScoped and Flash Scope in the #Named, something like this article. Flash scope implementation has yet to be seen, but the closest one i can get so far is this page.
Hopefully, replacing weld with spring as the jsr 299 implementation will still enable me to use #ConversationScoped.
Gotta test things now, wish me luck :-)
UPDATE 18 MARCH 2011
Successfully make use of Spring 3 instead of weld to do the #Named, #Inject. The important thing is to set the el-resolver in the faces-config.xml.
AFAIK, Spring 3 currently doesnt support CDI yet, so bye2 #ConversationScoped.
For the scoping, i must still use #Scope("request") or #Scope("session"), but if i prefer the #RequestScoped (javax.enterprise.context.RequestScoped) and #SessionScoped, i can make use of the bridge provided from this article.
The Scope("view") for spring from this article works like magic :-)
One problem remain though, how to pass objects between Scope("view")-beans ..
Wish me luck !
update
Ahhh .. finally done ..
Passing the variables using Flash provided by JSF2 really works like magic.
I dont need an 3rd party implementation for that.
So basically, i can do without weld, but with spring, with the common scopes available, including the view scope, dan can pass between beans using the flash object.
One thing missing is the conversation scope, which isnt a major problem to me yet.
Hopefully the future spring can support this conversation scope.
Cheers :-)
I can successfully Inject Spring bean using ManagedProperty annotation like below. This is on JSF Managed Bean. Spring bean is for backend and I prefer spring for backend.
#ManagedProperty(name="userRepository", value="#{userRepository}")
private UserRepository userRepository;
//Setter and/or Getter
value is the most important thing here. It's actually the bean name of spring. I hope this helps.
Weld (actually, the reference implementation of JSR-299 Context and Dependency Injection, also known as Java EE 6 CDI) was less or more invented to supplant Spring in Java EE 6 environments. I would suggest to use Java EE 6 CDI instead of Spring. Why would you use a 3rd party framework when Java EE 6 provides the same functionality out the box?
If the Spring backend really cannot be changed, then I'd suggest to stick to it and not to intermix with Java EE 6 CDI annotations to save yourself from confusions and maintenance headache.

CDI Bean accessing Spring beans?

I know this sounds strange, mixing CDI (Weld) and Spring for the controller.
But imagine this situation :
With CDI, i can make use of the #ConversationScoped, which is one of my requirement (And so far i dont know whether i can use spring for this kind of scope, because if i can, i could just replace Weld with Spring, with the el-resolver in faces-config.xml)
My services objects(#Service) along with the DAOs(#Repository) are to be managed by Spring
Now one question arise is that, inside my controller, how can i access my service object ?
Something like this wouldnt work i think :
#Named
#ConversationScoped
public class MyBean {
#Named
private SomeOtherBeanManagedByCDI myOtherBean; // this will work
#Autowired
private MySpringBean mySpringBean; // dont think that this will work
....
}
Any ideas on how to make use of spring beans inside a cdi bean ? Thank you !
update
I've just tested the solution from this article, and so far it works fine, and i feel relieved.
Thank you !
Rick Hightower wrote a nice Extension library which supports to inject Spring beans into CDI beans and vice versa:
http://rick-hightower.blogspot.com/2011/04/cdi-and-spring-living-in-harmony.html
There is still a good accepted answer and some good edits in the OP, but I think there still is time to point out the Seam Spring module.
Also, if you're trying to manage state across a series of pages, and want the effective of conversation management for Struts or JSF or Spring MVC, Spring Web Flow provides just what you need, complete with flow-scoped beans that live for the duration of a flow, more or less equivalent to a conversation in Seam / CDI. If you want a more long lived flow managment solution, the Activiti SPring module makes it dead simple to configure some beans that live for the duration of the process scope, akin to the functionality that Seam had for jBPM.

Resources