How to achieve multiple #managedBean value in JSF [duplicate] - jsf-2

I searched similar questions but I'm a bit confused. I have a login page, so LoginBean also which is;
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private String password="";
private String image="";
#ManagedProperty(value = "#{loginBeanIdentityNr}")
private String identityNr="";
...
after success, navigates to orderlist page, so I have also OrderBean.
#ManagedBean(name = "OrderBean")
#SessionScoped
public class OrderBean {
List<Ordery> sdList;
public List<Order> getSdList() {
try {
String identityNr ="";
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
LoginBean lBean = (LoginBean) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, "loginBean");
identityNr =lBean.getIdentityNr();
sdList = DatabaseUtil.getOrderByIdentityNr(identityNr);
...
}
I don't need the whole LoginBean, just ManagedProperty "loginBeanIdentityNr". But this code below doesn't work (of course);
identityNr = (String) FacesContext.getCurrentInstance()
.getApplication().getELResolver()
.getValue(elContext, null, "loginBeanIdentityNr");
this time it returns null to me.
I think if I need whole bean property, I can inject these beans, right? So, do you have any suggestions for this approach? can<f:attribute> be used?

The #ManagedProperty declares the location where JSF should set the property, not where JSF should "export" the property. You need to just inject the LoginBean as property of OrderBean.
public class OrderBean {
#ManagedProperty(value="#{loginBean}")
private LoginBean loginBean; // +setter
// ...
}
This way you can access it in the OrderBean by just
loginBean.getIdentityNr();
Alternatively, if you make your OrderBean request or view scoped, then you can also set only the identityNr property.
public class OrderBean {
#ManagedProperty(value="#{loginBean.identityNr}")
private String identityNr; // +setter
// ...
}
Unrelated to the concrete problem: initializing String properties with an empty string is a poor practice.

Related

Spring IOC w/ generics - inject dependencies based on dependent's type parameter

I want to instantiate a generic bean with a type parameter, and have the correct dependents wired based on this type parameter.
Suppose I have:
#Named
public Parent<T> {
#Inject
Parent(Child<T> c) {
...
}
}
public interface Child<T> {}
#Named
public class ChildString implements Child<String> {}
#Named
public class ChildInteger implements Child<Integer> {}
And then I want to use Parent like this:
#Named
public class UseParent {
#Inject
Parent<String> p;
}
Spring will complain with "expected single matching bean but found 2: childString, childInteger".
What is the best way to have wire my beans in this scenario?
I haven't found a satisfactory way of doing this. The solution I'm using for now is to create a subclass of Parent that specifies the generic type, eg:
#Named
public ParentString {
#Inject
ParentString(Child<String> c) {
super(c);
}
}
#Named
public class UseParent {
#Inject
ParentString p;
}

JSF view parameter fails when accessing method defined with generics

I have uncovered some strange behavior trying to set a value with a view parameter. The code below does NOT work...upon submission of the form with the view parameter, the id value is NOT set. However, if the comments are removed from the getId and setId methods, the id value IS properly set. Is there some issue with JSF EL when accessing generics, or am I doing something terribly wrong? Can anyone explain this behavior?
Interestingly, I receive no exceptions...the value is simply not set. In fact, the setId method in the abstract class is not even called.
public abstract class AbstractBusinessObjectAction<E, ID extends Serializable> {
protected abstract BusinessObjectManager<E, ID> getBusinessObjectManager();
public ID getId() {
ID id = getBusinessObjectManager().getId();
return id;
}
public void setId(final ID id) {
getBusinessObjectManager().setId(id);
}
}
#Named("configuration")
#ConversationScoped
public class ConfigurationAction extends AbstractBusinessObjectAction<ConfigurationParameter, Long> {
#Inject
private ConfigurationParameterManager manager;
protected BusinessObjectManager<ConfigurationParameter, Long> getBusinessObjectManager() {
return manager;
}
// public Long getId() {
// Long id = super.getId();
// return id;
// }
// public void setId(Long id) {
// super.setId(id);
// }
}
Following is an except from the .xhtml:
<f:metadata>
<f:viewParam id="entityIdParam" name="entityId" value="#{configuration.id}" />
</f:metadata>
Adding a converter solved the problem.
<f:viewParam id="entityIdParam" name="entityId" value="#{configuration.id}" >
<f:converter converterId="javax.faces.Long" />
</f:viewParam>
To the best of my knowledge, this is the reason:
Because the id property is of type ID extends Serializable in the abstract class, JSF tries to install a non-existant Serializable converter. The reason the code works when I uncomment the methods indicated, is that JSF properly detects that it needs a javax.faces.Long converter based on the explicit declaration of Long on the property methods for the "id" property.
Thanks to #Damian for the tip!

JSF 2.0 Accessing Application Scope bean from another Bean

I am using jsf 2.0 and I have two bean Navigation (Application Scope ) and Module (Request Scope). I want to use methods of Navigation bean in Module Bean. I am doing in this way
In Module Bean
#ManagedProperty(value = "#{navigationBean}")
private NavigationBean navigationBean;
But when I am trying to get navigationBean.SomeMethod it is not working as navigation bean is null . How to do this?
The both beans needs to be a fullworthy #ManagedBean. The acceptor should have a public setter method for the injected bean. The injected bean is only available in #PostConstruct and beyond (i.e. in all normal event methods, but thus not in the constructor of the acceptor).
So, this ought to work:
#ManagedBean
#ApplicationScoped
public class Navigation {
// ...
}
#ManagedBean
#RequestScoped
public class Module {
#ManagedProperty(value="#{navigation}")
private Navigation navigation;
#PostConstruct
public void init() {
navigation.doSomething();
}
public void setNavigation(Navigation navigation) {
this.navigation = navigation;
}
}
I think #ManagedProperty requires a public set method to work.
I got The solution
I have a method in application signature boolean getReadAccess(String role, String module ). If i want to use in another bean then i have to follow these steps
`javax.el.MethodExpression readAccess;
javax.el.ELContext elContext = null;
javax.faces.context.FacesContext context = FacesContext.getCurrentInstance();
elContext = ((FacesContext) context).getELContext();
javax.faces.application.Application application = FacesContext.getCurrentInstance().getApplication();
javax.el.ExpressionFactory expressionFactory = application.getExpressionFactory();
readAccess = expressionFactory.createMethodExpression(elContext,
"#{navigationBean.getReadAccess}", Void.class, new Class[] {
String.class, String.class });
//--------Call----------------------------
return (Boolean) readAccess.invoke(elContext, new Object[] {
"roleName", "moduleName" });
`

JSF 2.0 + Primefaces richtext editor

<p:editor value="#{editorBean.value}" widgetVar="editor" width="686"
height="390" language="en" align="center">
</p:editor>
Following is my rich-text editor bean picked up from primefaces
#ManagedBean(name = "editorBean")
#SessionScoped
public class EditorBean {
private static final String MANAGED_BEAN_NAME = "editorBean";
private String value;
public static EditorBean getCurrentInstance() {
return (EditorBean) FacesContext.getCurrentInstance()
.getExternalContext().getRequestMap().get(MANAGED_BEAN_NAME);
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Apart from this I have another bean say A. I have a method inside A that populates a HTML table. What I want is when the user opens the editor, it should be pre-populated with that HTML table data and of course the changes should get reflected into (String: value). Therefore, you can say that I am trying to tie up both the values together. I think it needs to be done with DI but somehow its not working. If someone can guide or quote an example, it would be really helpful.
One way to do it is rewrite your getValue() method to pick up the value from bean A.
And yes, the reference to your A bean should come from DI:
//injecting a reference to A
#ManagedPropery(value="#{A}") //or whatever is the name of your bean
private A beanA;
public void setBeanA(A beanA) {
this.beanA = beanA;
}
Or, with CDI, just:
#Inject private A beanA
Finally, your getValue method
public String getValue() {
return beanA.getValue()
}

ASP.NET MVC - Ninject 2.0 Activation Error

I just started working with dependency injection for the first time and I am using as Ninject 2.0 as my IoC container in an ASP.NET MVC 2 website and I'm hitting an activation error that I am not sure how to react to. I am sure it's simple so hopefully someone can point me in the right direction without too much thought.
I have a property on my class BaseController which takes an IWebsiteSettings and is flagged with the [Inject] attribute. In my StandardKernel I load a module with the following code:
public class WebModule : Module
{
public override void Load()
{
Bind<IWebsiteSettings>()
.ToProvider(new WebsiteSettingsProvider(WebConfigurationManager.AppSettings))
.InSingletonScope();
}
}
public class WebsiteSettingsProvider : Provider<WebsiteSettings>
{
private const string WebsiteNameKey = "Website.Name";
private const string ContactFormEmailSubjectKey = "ContactForm.EmailSubject";
private const string ProductImageDirectoryKey = "Products.ImageDirectory";
private const string UploadTempDirectoryKey = "Uploads.TempDirectory";
protected NameValueCollection Settings { get; set; }
public WebsiteSettingsProvider(NameValueCollection settings)
{
Settings = settings;
}
protected override WebsiteSettings CreateInstance(IContext context)
{
return new WebsiteSettings
{
WebsiteName = Settings[WebsiteNameKey] ?? string.Empty,
ContactFormEmailSubject = Settings[ContactFormEmailSubjectKey] ?? string.Empty,
ProductImageDirectory = Settings[ProductImageDirectoryKey] ?? string.Empty,
UploadsTemporaryDirectory = Settings[UploadTempDirectoryKey] ?? string.Empty
};
}
}
This is fairly straightforward- I'm trying to load some data from the web.config file and store it in a singleton object for use across my controllers. The call to Bind seems to function exactly as it should and the Settings property in my provider is correctly initialized with the AppSettings collection in the config file. Still, when the application loads the first time:
Server Error in '/' Application.
Error activating SByte* using implicit self-binding of SByte*
No constructor was available to create an instance of the implementation type.
Activation path:
4) Injection of dependency SByte* into parameter value of constructor of type string
3) Injection of dependency string into property WebsiteName of type WebsiteSettings
2) Injection of dependency IWebsiteSettings into property WebsiteSettings of type HomeController
1) Request for HomeController
Suggestions:
1) Ensure that the implementation type has a public constructor.
2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead.
Interestingly, if I refresh the page I don't get the exception and a call to Kernel.Get() returns the correct object.
Any advice?
(We talked about this on IRC, but I'm putting it here in case someone else runs into this problem as well.)
WebsiteSettings has [Inject] attributes on its properties, so Ninject is trying to resolve a binding from System.String to inject a value into the properties. Since you're using a custom provider to activate WebsiteSettings instances, you don't need [Inject] attributes on its properties.
The offending code was actually in the class WebsiteSettings where I was doing this:
public class WebsiteSettings : IWebsiteSettings
{
[Ninject.Inject]
public string WebsiteName
{
get; set;
}
[Ninject.Inject]
public string UploadsTemporaryDirectory
{
get; set;
}
[Ninject.Inject]
public string ContactFormEmailSubject
{
get; set;
}
[Ninject.Inject]
public string ProductImageDirectory
{
get; set;
}
}
By placing the Inject attribute on my properties I was causing Ninject to try to assign values that I never bound. Because I am using a Provider to load my type I do not need to include the Inject attribute.

Resources