How to inject a JSF bean into a spring bean - spring

I'm working on a legacy JSF application which we are slowly porting over to Spring MVC. We are using Spring Security to control login information. After logging the user in, the JSF pages globally instantiate a session scoped bean that is used everywhere. I'd like to change the application so that we can go to a page that was developed with Spring MVC first.
One approach I tried was to convert the bean into a spring bean and have it injected into JSF, but unfortunately that turned out to require a lot of changes to the bean to make it possible. One possible hack I thought of is to add a special redirecting JSF page to initialize the JSF beans before sending the user to the Spring MVC page. That seems like quite a bit of a hack though so I'm looking for another solution.
Is there some other way that I can force the session scoped bean to be initialized before I go to my Spring pages so that I can just pull the bean out of session?

If you are using Spring MVC, you can make your "bean" a Model Attribute, then have it auto-loaded into session using a combination of annotations on the Controller, handler methods, and a method that creates an instance of your bean. Your controller would look something like this:
#Controller
#SessionAttributes({"myBean"})
#RequestMapping("/myPath")
public class MyController {
#RequestMapping("/myPath2")
public String myHandler(#ModelAttribute("myBean") MyBean myBean) {
// ...do stuff, return view
}
#ModelAttribute("myBean")
MyBean createMyBean() {
// Create and init an instance
return new MyBean();
}
}
You will get a MyBean magically created for you whenever there isn't one, and any time you update the Model (or ModelAndView) with "myBean", it will also get magically added to the Session.

Related

Ajax calls are not working when bean is changes to #Scope("request") with PrimeFaces

I am new to Spring/JSF.
I have a controller which is annotated by #Component which have a #Autowired class UserClass which has,
#Scope(value=org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE)
I need to create a new UserClass instance for each new request so my controller is annotated with #Scope("request") which works perfectly(Creating new instance for each request) with this annotation.
But it broke the ajax calls in <p:dataTable> selection, commondLink, <f:setPropertyActionListener...
NOTE : if I change the #Scope("request") to #ViewScoped the ajax works but my UserClass becomes singleton and all the data is shared between the threads.
I googled and got to know we need to either use JSF annotations or Spring but here I am using only Spring annotations.
And I found this, PrimeFaces doesn't work when bean scope is request but couldn't understand.
A component library like Primefaces heavily relies in a stateful model, which means using at least the view scope in your managed beans. If you use the request scope you'll be recreating the managed bean for every single request, including ajax requests, which I guess it isn't what you want (not the way to go with JSF, at least).
Your best is to use a custom Spring Scope in order to emulate the JSF view scope. I like this approach from the PF team (a bit old post, but still you can tune it for newer Spring versions) or this one, which is more elaborated.

Spring in a JavaFX application - how to property handle controller as dependency?

I have a JavaFX application that uses spring boot, exactly as described in this blog post:
http://www.greggbolinger.com/let-spring-be-your-javafx-controller-factory/
I am using the FXML loader overriding the controller factory to use spring.
The problem is that Spring loads the controller class marked as #Component on application start or later if marked with #Lazy, but keeps the bean in memory.
If I open a Stage, modify the data, close the stage and open it again, the data is still there (because the controller was kept by spring). It also gets in the way if I open two of the same Stage (window). It shares the same controller, so if I modify one, the other modifies too, and this is not the desired behavior.
How to I properly handle JavaFX controllers with spring?
Thanks!
Mark the controller as having prototype scope, so that a new instance is created on each request:
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class Controller {
// ...
}

when will JSF #PostConstruct be called again?

I'm making an application with spring+primefaces
I created a init function in managed bean to load some useful data (the bean is #ViewScope)
#PostConstruct
public void init(){
log.debug("initing....");
currentUser = UserUtil.getCurrentUser(this.userManager);
loadData();
}
later in view I have some tags to hide columns like this:
<p:column rendered="#{dataManagedBean.currentUser.manager}"> // to test if the current user is a manager role
...
...
</p:column>
the problem is when I login with a normal user, then even logout and login with manager user, the column I want to show is not showing, because the init() method is not calling again therefore the "currentUser" remains the oldone (normal suer)
UPDATE
the problem maybe I mixed Spring DI and JSF managed beans, there is more detail
in javabean layer: I used #Entity annotation for hibernate
in dao layer: I use #Repository("DataDao") to inject the daos (from
spring)
in manager layer: I use use many spring annotations to inject like
#Service("DataManager") #Authowire #Qualifier etc
in view layer, since I have been using spring to inject, thats why I
use #Component("DataManagedBean") and #ViewScope
I have been 2 weeks with the application, and everything worked as expected. untill I found today #PostConstruct is actually never call again, the view is never destroy :S (or it's intented to work like this, a singleton...)
Can someone kindly explain me where I did wrong?
After an intensive reading about JSF scopes, specially thanks to #M. Deinum's comments and Mr #BalusC's excelent article explaining about the JSF communication topic. I understand why the user object survived event after logout/relogin.
My mistake is combining Spring DI (by using #Component annotation) and JSF annotation (by using #ViewScoped), then the #ViewScoped annotation is ignored and default spring scope is used, which is by default a singleton...

injecting spring beans into non-singleton classes

is it possible to inject spring beans into a polling filter class (FClass) controlled by a scheduler job?
i don't quite understand how singleton applies here.
i understand spring beans are singleton so in order to inject the spring beans into class FClass. i need to define FClass as a bean and add the DI as property etc..
so how do i know if FClass should be a singleton? i assume only classes that are singletons can be created and beans and have DI done to them.
my problem is :
i need to be able to inject my facade bean xfacade into FClass. x_facacde handles the dao object. it has Y_dao and a Z_hibernate session beans injected as DI.
when i tried to create a spring bean of StatusPollingFilter (FClass) and injected the facade bean - i got a null and the setter is never called for the injection in debug mode.
the problem:
i'm thought it might be something to do with the thread / scheduler nature of StatusPollingFilter, and since spring beans are singletons it might not work due to that.
i'm thinking of creating a factory for the StatusPollingFilter (FClass). but need to know if this is correct thing and i'm on right track before i do too much work and realize even that doesn't work as the problem might be somewhere else. ideally i just want to update a table in the easiest possible way. but i have to use hibernate as the DAO exists but hibernate is configured using
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
with /hibernate/TopoObject.hbm.xml
files.
so no matter how i try this i always get null pointer exception on session or injected facade bean.
reading some of the QA's here seems like because StatusPollingFilter is instantiated using the scheduler and not spring it cant be aware of the DI beans. so would the above factory pattern help here.
I may have an additional problem but i'll cross that bridge when i come to it. but just to mention briefly, in case anyone is aware of issues that i might hit ... not sure what / how the scheduler would invoke the factory for an instance as its all controlled by 3rd party api - which invokes a StatusPollingFilter but i'm assuming if i pass in the factory as the class and parameter it would find its way through... but initial part is the main question. please ignore the latter waffle. thanks in advance.
Actually :
i assume only classes that are singletons can be created
is where you are wrong.
A bean is just a class that you let spring instantiate. By default, they are created as singleton but you can specify the scope on your bean using the attribute scope (quite surprisingly). The value you can specify are those specified in the documentation here
So one thing you have to be careful with is the injection of beans scoped as prototype or request into singletons.
having read more - i have come across the ans.
because the StatusPollingFilter object is under control of scheduler (i knew that scheduler had something to do with it) then it is unaware of the spring beans which is why i keep getting null when i try injecting the bean.
i created a class:
ApplicationContextProvider implements ApplicationContextAware
added static access
private static ApplicationContext appContext;
did a setter for it :
public void setApplicationContext(ApplicationContext context)
{
appContext = context;
}
and added
public static Object getBean(String beanName) throws BeansException
{
return appContext.getBean(beanName);
}
used in code as :
EvoTAMDAOFacade evoDao = (EvoTAMDAOFacade) ApplicationContextProvider.getBean("evoDaoFacade");
i now have access to the facade bean and all injected beans into facade.
i still have an issue with hibernate session but thats prob due to some other issue.
pt here is i don't have access to the bean as its not in control of the spring container so i needed to somehow get it , probably could have done it via the factory method but why mess around when there a simpler way.
thanks for help by anyone who may have posted or tried to understand my problem.

Clean way to inject a Spring 3 bean into a JSF 2 managed bean?

I'm migrating our current solution from JSF 1.2 to JSF 2. As I need to use the new View scope I'm using JSF 2 annotations. That forced me to inject the Spring beans using the JSF #ManagedProperty annotation instead of Spring's #Autowired
Before it was something like this:
#Autowired private OneService oneService
And now it's like:
#ManagedProperty(value="#{oneServiceImpl}")
private OneService oneService
Do you know if is there a way to annotate the managed properties without needing to state their bean name?
Thanks!
No, there isn't. JSF makes use of Expression Language (EL) to determine which class you refer by name. Using a class called ELResolver he takes the String passed, interprets and makes the appropriate reference. The class SpringBeanFacesELResolver provides integration between the two frameworks intercepts the request and passing it to the context of Spring, which handles the dependencies required to provide the ManagedBeans, who then passes it to the JSF's own ELResolver. So JSF needs the name of the bean to know what to inject.
You can still use Spring with JSF 2. Just create a custom Spring scope which can then be used as the view scope for your beans.
#Named #Scope("view")
public class MyBean {
#Inject
private MyManagedProperty oneService;
//...
}
Steal the implementation of the View scope here: http://cagataycivici.wordpress.com/2010/02/17/port-jsf-2-0s-viewscope-to-spring-3-0/

Resources