I am trying to figure out a solution for a small problem I have encountered whilst developing a small application. I am trying to pass an object created within one backing-bean and then later using that same object I created within another backing-bean. However, I would not like to make these backing-beans #SessionScoped, and preferably not use the #ManagedBean as I am using CDIfor my JavaEE application.
Is there anyway I could do this using CDI annotations and injecting one backing-bean to another and then have the ability to access that object previously created?
As an example, refer to the below beans:
#Named
#ViewScoped
public RegisterController implements Serializable {
User user = new User();
// Getter and Setter methods which are populated by the JSF page
}
Get Object User created within the above bean and use it within the controller below:
#Named
#ViewScoped
public PaymentController implements Serializable {
#Inject RegisterController registerController; // Injecting bean
registerController.getUser().getName(); //this is null when I try access the properties of the object 'User'. I am assuming this is because #ViewScoped annotated on the 'RegisterController' class?
// I would like to use the User object created in 'RegisterController' here an access properties etc...
}
Could I use the #Inject annotation offered by the CDI?
UPDATE
Ok, so I have got the above working when I annotate the RegisterController with the SessionScoped annotation, however I do not want this Bean annotated SessionScoped as I will probably run into further implications down the track, such as pre-population of fields, etc... Any ideas how to implement this any other way?
Well, #ViewScoped is too short to the purpose and #SessionScoped is too long. Then why not use #ConversationScoped?
See here.
you can use in RegistrationController:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", user);
and in PaymentController:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("user");
this is very useful, you can save the objects you want in the map.
Related
I have class which I created manually using new, because I needed to pass it some objects (not beans). It has 2 objects tough which I want to be autowired by spring. This is my class:
#Component
#Scope("prototype")
public class DayLayout extends VerticalLayout {
#Autowired
private SchedulingService schedulingService;
#Autowired
private GeneralService generalService;
.
.
.
}
But after creation of the class those objects are still null. I think it is because I have not obtained that bean via spring container. But is there any way how can I create object manually and all it's objects will be still autowired ?
So if you need to inject Autowired properties to an object created via new you could do the following:
DayLayout dl = new DayLayout(<whatever parameters go here>);
ctx.getAutowireCapableBeanFactory().autowireBean(dl); // Where ctx is Spring's application context
But if you need to do such things I think you might rethink what you are actually doing in your application.
Assuming that GeneralService is not a class annotated with #Component or other Spring stereotypes annotations: yes, there is.
#Configuration
public class ConfigClasses{
#Bean
public GeneralService generalService(){
return new GeneralService();
}
}
Obviously the same for SchedulingService, just add another method which produces that class.
I think you are misunderstanding some part of managed objects, but I am not sure what part that is.
Since you annotated the bean as #Prototype I assume you realize Spring will instantiate a new instance for you every time you request one. It would then be a trivial matter to call setters for your non-managed objects. You could even add a belt and suspenders approach and have your bean throw a IllegalStateException if the setters have not been called.
#Ivan is exactly correct on how you can manually request a bean. He is also exactly correct that if you are resorting to that your design is probably not the best.
If you do : Object obj = new Object(); , it won't autowire. If you want to create manually your object, you can use a config file with #Configuration and return a #Bean. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html . If that is not what you want, can you provide how you create those two objects ? What do you pass to them ?
In this example, why does it need the #ManagedBean annotation? In the setPalyBean() method, it receives a parameter and set it to the the private variable "playerBean". This is just like a regular Java class design in non-JSF world. Would it work the same if the #ManagedBean is removed?
#Named
#SessionScoped
public class PlayersBean {
private String playerName;
private String playerSurname;
public PlayersBean() {
playerName = "Rafael";
playerSurname = "Nadal";
}
//getters and setters
}
#ManagedBean
#ViewScoped
public class ProfileBean {
#ManagedProperty("#{playersBean}")
private PlayersBean playersBean;
private String greetings;
public ProfileBean() {
}
public void setPlayersBean(PlayersBean playersBean) {
this.playersBean = playersBean;
}
}
Those are the rules:
#ManagedBean - required if you:
Want to access your bean from the view, in old-style JSF
Want the container to manage the injection of anything into the bean, in old-style JSF
Want the container to manage the lifecycle of your bean, ...
Want to name your bean something different from the standard class name. The default naming convention is converting the class-name to a standard java, so what you'll have there is a bean named proileBean. If you wanted to address that bean by a different name, say profile, you'll need to use this annotation
#ManagedProperty and the associated setter are required, if you want the container to automatically inject anything into your bean. Them's the rules. It boils down to how the injection happens - Reflection.
Will it work without the annotation? No - without that annotation (and depending on your version of JSF; 2.2 allows all kinds of stuff), the container isn't aware of your bean and won't be prompted to take action
You can save yourself the hassle and adopt CDI conventions:
Replace #ManagedBean with #Named (this annotation is required only if you need to access the bean within a page, otherwise, it's unnecessary -Every bean in a CDI context is automatically managed)
Replace #ManagedProperty with #Inject. With this annotation, you can ditch the setter and getter altogether. You also don't need to worry about the scope of the bean that you're injecting into or from.
Replace your current #ViewScoped with the one from javax.faces.view.ViewScoped
I was creating my first application using Apache wicket and am stuck on a problem. After the user logs in through the authentication method I have a new session which is created for that user. Now if I wanted to have data stored for just that user how would I use bean to implement that?
At the moment i created an interface and a class with get and set methods for the variables i wanted stored and created a bean such as <bean id="springApplicationContext" class="com..util.SpringApplicationContext"/> but what happens is the data gets overwritten but when i change the scope to "session" everyone has the same data in the bean still.
Thanks
The correct way is to use Session scoped Spring bean. There must be some error in your config if the data is visible to all users.
Using Spring has nothing to do with Wicket though!
Alternative approach is to store your data in Wicket's Session class.
Override MyApplication#newSession() method and return MySession class. The instance of MySession will be stored as an attribute in the HTTP session by Wicket. You can put any member fields inside MySession, e.g.;
public class MySession extends WebSession {
...
private MyBean myBean;
// setter and getter
...
}
Then in your Wicket code use it with: MySession.get().getMyBean().setSome(thing);
How can I inject this class (It's inside the war part of the project):
#Named("user")
#SessionScoped
public class User implements Serializable
{....}
Into this EJB session bean:
#Stateless
#LocalBean
public class testSB
{ inject User here... }
I tried using #Inject but it does not work. It seems that it does not recognize User class.
I tried looking for an example of injecting CDI into EJB, but could not find anything that worked.
Is that even possible? What is the right way to do this? I would like to get data from the User class directly instead of passing the values inside the methods.
Inject a Provider<User> into your stateless bean. Then, when you need the user, do userProdiver.get().
Pay attention to not instantiate a "testSB" object (in this way you can't expect the container to inject an object of class "User" to you). To the container be able to inject one object of class "User" to you, you MUST let the container instantiate the object of class "testSB".
I don't think that there is a problem in injecting a "SessionBean" inside a "RequestBean". All your "RequestBean" objects will share the same object of the "SessionBean" class.
With CDI you should be able to inject anything anywhere, even in EJB SessionScoped.
Try adding an empty beans.xml to your META-INF. Please check my answer here:
Java EE 7 - #Decorator, #Stateless and #PersistenceContext = nullpointerException
Best Regards,
Alexander
i want to use 2 different beans (Spring) for one JSF-Page. I do not like to write every method into one bean, so i tried to separate into two beans like JobEditDataBean and JobEditActionBean.
I want to use the JobEdiDataBean just as "Container" for my data objects and move the actionstuff (like saving, update etc.) to the action bean.
What i did by now (and what seems to work, but feels wrong) is the following:
public class JobEditDataBean{
#Autowired
JobEditActionBean actionBean;
// some objects...
#PostConstruct
public void init() {
actionBean.setJobEditDataBean(this);
// do something ...
}
}
public class JobEditActionBean{
JobEditDataBean dataBean;
// some objects...
}
Do you have any hints or tipps how this can be done better, nicer?
Indeed, you don't need to have one bean per each page. You can use as much beans you want for any page, it is fine, as whenever an expression like #{someMB} is found in your XHTML, JSF will find a bean with that name and create a new instance if necessary.
If you need to inject one bean to another, just use #Autowired already:
#Component
#Scope("request")
public class JobEditActionBean {
#Autowired
private JobEditDataBean dataBean;
#PostConstruct
public void init() {
// dataBean.youCanUseDataBeanMethodsHereAlready()
}
}
You just have to make sure both beans are in the Spring container (annotating them with #Component will do), and choosing the right scope for each one. Beware of the scopes of the beans which you are injecting, cause it usually only makes sense to inject beans of broader scope to beans of the same or more restrict scope.
Having said that, I recommend reading following thread about choosing the right scopes:
How to choose the right bean scope?
One more thing: this is only valid if your JSF beans are really being managed by the Spring container (that was my assumption after you used #Autowired). If you are letting JSF container manage the beans (using #ManagedBean with #RequestScoped or #ViewScoped, for example), the way you inject them is with a #ManagedProperty annotation:
...
#ManagedProperty("#{jobEditDataBean}")
private JobEditDataBean dataBean;