What's the difference between:
public class GameController implements Serializable{
#ManagedProperty(value="#{Gamebean}")
private Game game;
and
public class GameController implements Serializable{
private Game game;
public GameController(){
game =(Game)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("Gamebean");
}
and if there's no difference what method is better ?
Cheers.
The #ManagedProperty way will autocreate bean if it doesn't exist yet. The getSessionMap() way won't and may thus return null if bean isn't (auto)created beforehand.
The code which achieves the same with least effort and concern is better.
Related
I have a jsf bean used in pretty much all jsf beans in the application and I prefer not to hardcode the bean name when injecting the bean instance. Is it possible make it a variable and use the variable everywhere?
#ManagedBean (name=ApplicationInfo.BEAN_NAME_APPLICATION_INFO, eager=true)
#ApplicationScoped
#SuppressWarnings("serial")
public class ApplicationInfo extends ParentBean
{
public static final String BEAN_NAME_APPLICATION_INFO="applicationInfo";
.....
}
Now the referring class
#ManagedBean
#ViewScoped
public class SearchResultsBean extends ParentBean
{
private static final long serialVersionUID = 1L;
#ManagedProperty (value="#{ApplicationInfo.BEAN_NAME_APPLICATION_INFO}")
private ApplicationInfo applicationInfo;
....
}
Is it even possible?
Thanks
No, sorry, you can't set a variable name for a managed bean.
Here you have the link to the docs of the ManagedBean annotation
https://docs.oracle.com/javaee/6/api/javax/faces/bean/ManagedBean.html
You can see that "Classes must be scanned for the presence of this annotation at application startup, before any requests have been serviced."
So the name of the bean maybe only a hardcoded String. Every evaluation (such as calculate the value of ApplicationInfo.BEAN_NAME_APPLICATION_INFO) would happen later, when the application is started.
My problem is te data is not refresh in the datatable. I want to destroy the session scoped when I clicked to the item in the menu.I know that it's possible with Viewscoped but I want to learn other way.
Thank in advanced.
Controller:
#ManagedBean
#SessionScoped
public class MyController implements Serializable {
//getters and setters
...........
}
Menu:
<td><h:outputLink styleClass="itemOutputLink" value="# {request.contextPath}/pages/page.faces">Page1</h:outputLink></td>`
There is no really "clean" way of doing that. A #SessionScoped bean should live as long as a Session. Thus I emphasize again that you should better adjust the beans scope.
But if you really still need to do it, the easiest way would be to do it like this:
public static void removeSessionScopedBean(String beanName)
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(beanName);
}
For #ViewScoped beans you could do it this way:
public static void removeViewScopedBean(String beanName)
{
FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(beanName);
}
I'm new in Java EE/JSF and now read about CDI qualifiers - the possibility to change class implementation. This is great but I have got one question. As far as I understand I can change class implementation using qualifier but I need to change it everywhere I use this implementation. What is the best solution to do it in one place? With my small knowledge about Java EE I figured out this one.
Lets imagine that we are creating simple Calculator application. We need to create few classes:
Calculator (basic implementation of calculator)
ScientificCalculator (scientific implementation of calculator)
MiniCalculator (with minimum potentiality)
MockCalculator (for unit tests)
Qualifier #Calculator (will indicate to the actual implementation of calculator; should I create qualifier for each implementation?)
Here is the question. I've got four implementations of calculator and I want to use one of them in few places but only one at time (in the initial project phase I will use MiniCalculator, then Calculator and so on). How can I change implementation without change code in every place where object is injected? Should I create factory which will be responsible for injecting and will work as method injector? Is my solution correct and meaningful?
Factory
#ApplicationScoped
public class CalculatorFctory implements Serializable {
private Calculator calc;
#Produces #Calculator Calculator getCalculator() {
return new Calculator();
}
}
Class which uses Calculator
public class CalculateUserAge {
#Calculator
#Inject
private Calculator calc;
}
Is this the correct solution? Please correct me if I'm wrong or if there is a better solution. Thanks!.
There are several issues here.
What is the best way to change the desired implementation in the entire application? Look into #Alternatives.
Do I need a qualifier for each implementation? No, see this answer for a lengthy and detailed explanation.
Should I use a producer to decide which implementation is injected? Could be the solution you want, but I doubt it. Producers are generally used to perform some sort of initialization that can't be done in the constructor / #PostConstruct. You could also use it to inspect the injection point and make runtime decisions about what to inject. See the link 2. for some clues.
Is this solution correct? This will work, but you'll still have to mess with the code to change the implementation, so consider 1. first. Also #Calculator Calculator seems highly redundant. Again, see the link at 2.
#ApplicationScoped
public class CalculatorFctory implements Serializable {
private Calculator calc;
#Produces #Calculator Calculator getCalculator() {
return new Calculator();
}
}
Update:
CDI uses qualifiers in addition to types for dependency resolution. In other words, as long as there is only one type that matches the type of the injection point, types alone are enough and qualifiers are not needed. Qualifiers are there for disambiguation when types alone are not enough.
For example:
public class ImplOne implements MyInterface {
...
}
public class ImplTwo implements MyInterface {
...
}
To be able to inject either implementation, you don't need any qualifiers:
#Inject ImplOne bean;
or
#Inject ImplTwo bean;
That's why I say #Calculator Calculator is redundant. If you define a qualifier for each implementation, you're not gaining much, might as well just use the type. Say, two qualifiers #QualOne and #QualTwo:
#Inject #QualOne ImplOne bean;
and
#Inject #QualTwo ImplTwo bean;
The example directly above does not gain anything since in the previous example no dis-ambiguity existed already.
Sure, you can do this for cases where you don't have access to particular implementation types:
#Inject #QualOne MyInterface bean; // to inject TypeOne
and
#Inject #QualTwo MyInterface bean; // to inject TypeTwo
However OP shouldn't be using #Produces when he wants Calculator implementations to be CDI managed.
#Avinash Singh - CDI manages #Produces as well as anything they return, as long as it is CDI that calls the method. See this section of the spec if you please. This includes returning `#...Scoped beans which will support dependency injection, life-cycle callbacks, etc.
I overlooked some details here, so consider the following two:
public class SomeProducer {
#Inject ImplOne implOne;
#Inject ImplTwo implTwo;
#Inject ImplThree implThree;
#Produces
public MyInterface get() {
if (conditionOne()) {
return implOne;
} else if (conditionTwo()) {
return implTwo;
} else {
return implThree;
}
}
}
and
public class SomeProducer {
#Produces
public MyInterface get() {
if (conditionOne()) {
return new ImplOne();
} else if (conditionTwo()) {
return new ImplTwo();
} else {
return new ImplThree;
}
}
}
Then, in the first example, CDI will manage the life cycle (i.e. #PostConstruct and #Inject support) of what's returned from the producer, but in the second one it will not.
Back to the original question - what's the best way to switch between implementations without having to modify the source? The assumption is that you want the change to be application wide.
#Default
public class ImplOne implements MyInterface {
...
}
#Alternative
public class ImplTwo implements MyInterface {
...
}
#Alternative
public class ImplThree implements MyInterface {
...
}
Then, any for any #Inject MyInterface instance, ImplOne will be injected, unless
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<alternatives>
<class>ImplTwo</class>
</alternatives>
</beans>
is specified, in which case ImplTwo will be injected everywhere.
Further Update
There are indeed things in the Java EE environment that are not managed by CDI, such as EJBs and web services.
How would you inject a web service into a CDI managed bean? It's simple really:
#WebServiceRef(lookup="java:app/service/PaymentService")
PaymentService paymentService;
That's it, there you'll have a valid reference to the payment service which is managed outside CDI.
But, what if you didn't want to use the full #WebServiceRef(lookup="java:app/service/PaymentService") everywhere you need it? What if you only want to inject it by type? Then you do this somewhere:
#Produces #WebServiceRef(lookup="java:app/service/PaymentService")
PaymentService paymentService;
and in any CDI bean that needs a reference to that payment service you can simply #Inject it using CDI like this:
#Inject PaymentService paymentService;
Note that before defining the producer field, PaymentService wouldn't be available for injection the CDI way. But it is always available the old way. Also, in either case the web service is not managed by CDI but defining the producer field simply makes that web service reference available for injection the CDI way.
If you want to swap the implementation in your code using a factory method then your factory method is managing the beans and not CDI and so there is really no need for #Calculator.
#ApplicationScoped
public class CalculatorFactory implements Serializable {
enum CalculatorType{MiniCaculator,ScientificCaculator,MockCalculator};
Calculator getCalculator(CalculatorType calctype) {
switch(calctype)
case MiniCaculator : return new MiniCalculator();
case ScientificCalculator : new ScientificCalculator();
case MockCalculator : new MockCalculator();
default:return null;
}
}
public class CalculatorScientificImpl {
private Calculator calc =
CalculatorFactory.getCaclulator(CaclutorType.ScientificCalculator);
doStuff(){}
}
public class CalculatorTest {
private Calculator calc =
CalculatorFactory.getCaclulator(CaclutorType.MockCalculator);
doStuff(){}
}
However if you want your Caclulator beans to be CDI managed for injections and life cycle management using #PostConstruct etc then you can use one of the below approaches.
Approach 1 :
Advantage :You can avoid creating annotation using #Named("miniCalculator")
Disadvantage : compiler will not give an error with this approach if there is a name change from say miniCalculator to xyzCalculator.
#Named("miniCalculator")
class MiniCalculator implements Calculator{ ... }
#ApplicationScoped
public class CalculatorFactory implements Serializable {
private calc;
#Inject
void setCalculator(#Named("miniCalculator") Caclulator calc) {
this.calc = calc;
}
}
Approach 2 : Recommended (Compiler keeps track of injection if any injection fails)
#Qualifier
#Retention(RUNTIME)
#Target({FIELD, TYPE, METHOD})
public #interface MiniCalculator{
}
#ApplicationScoped
public class CalculatorFactory implements Serializable {
private calc;
#Inject
void setCalculator(#MiniCalculator calc) {
this.calc = calc;
}
}
Approach 3: If you are using a factory method to generate your object.Its lifecycle wont be managed be CDI but the Injection will work fine using #Inject .
#ApplicationScoped
public class CalculatorFactory implements Serializable {
private Calculator calc;
#Produces Calculator getCalculator() {
return new Calculator();
}
}
public class CalculateUserAge {
#Inject
private Calculator calc;
}
All three approaches will work for testing , say you have a class named CaculatorTest,
class ScientificCalculatorTest{
Caclulator scientificCalculator;
#Inject
private void setScientificCalculator(#ScientificCalculator calc) {
this.scientificCalculator = calc;
}
#Test
public void testScientificAddition(int a,int b){
scientificCalculator.add(a,b);
....
}
}
if you want to use a mock implementation in your test then do something like this,
class CalculatorTest{
Caclulator calc;
#PostConstruct
init() {
this.calc = createMockCaclulator();
}
#Test
public void testAddition(int a,int b){
calc.add(a,b);
.....
}
}
I'm using JSF and am running in a problem for quite awhile, I've searched at a lot of places but couldn't find any suitable answer.
Can I have dependency injection working in an abstract (or more generally a class higher in the hierarchy) class ?
Also, how should we handle annotations when working with inheritance ? I've read that the common practice would be not to annotate the abstract class, only the concrete one, but then, it would imply no injection for that abstract ?
My problem is that one (check the last comment) :
Abstract class
#ManagedBean
#ViewScoped
public abstract class AbstractController<T extends VersionedObject> implements Serializable {
#ManagedProperty("#{libraryVersionController}")
private LibraryVersionController libraryVersionController;
public List<T> loadFromDatasource(IVersionedServiceBase<T> service) {
log.info("Loading generic VO from data source");
VersionedObjectFilter filter = new VersionedObjectFilter();
filter.setSelectedLibVersion(libraryVersionController.getSelectedItem());
// etc
}
// getters, setters...
}
Concrete class
#ManagedBean
#ViewScoped
public class DomainController extends AbstractController<Domain> implements Serializable {
private List<Domain> allItems;
private Domain[] selectedItem;
#ManagedProperty(value = "#{domainService}")
private DomainService domainService;
#PostConstruct
public void loadFromDatasource() {
allItems = super.loadFromDatasource(domainService);
// !! DOES NOT WORK, null pointer exception on abstract class (libraryVersionController)
// etc
}
Getters and setters are correctly set up, as I could read in my .xhml it is the concrete class that I'm referencing (#{domainController.allItems}), there is only one #PostConstruct. I'm using JSF2.1 and Mojarra.
Thanks for your help !
As to your NullPointerException, my guess is that AbstractController.setLibraryVersionController is missing. As I understand it, when the AbstractController is constructed (presumably it has an implicit constructor even though it's abstract), that method is needed to fill in the appropriate value.
I know you said all getters and setters are there, but this one seems tricky, so possibly you missed it. If you add logging to this method, you can check that JSF is attempting to fill in the value, and also check whether the value is null or not.
On the general question of how dependency injection works with the inheritance hierarchy, I would guess that your approach is OK, and that dependencies are injected for the base class and then for the derived class, down the chain.
I'm trying to inject the value of one sessionscoped bean into a viewscoped bean but it keeps returning null, here's a snippet:
import javax.faces.application.FacesMessage;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
//Class for managing the current logged-in user
#ManagedBean(name="user")
#SessionScoped
public class User implements Serializable{
private String userName;
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return this.userName;
}
And it's used in:
#ManagedBean(name="databrowser")
#ViewScoped
public class dataBrowser implements Serializable {
private List<UploadData> dataItems;
private SelectItem[] dataTypeOptions, qualityOptions, accessOptions;
private UploadData selectedData;
private String filelocation;
#ManagedProperty(value="#{user.userName}")
private String userName;
public String getUserName() {
return this.userName;
}
dataBrowser is used to populate a Primefaces datatable, when it's called userName is null and I'm not sure why.
Recently I have problem with injecting nested managed bean properties by #ManagedProperties too. Once injected it never changed. I did a workaround by evaluating EL in getter instead of injecting it.
Try that:
public String getUserName() {
FacesContext context = FacesContext.getCurrentInstance();
return (String) context.getApplication().evaluateExpressionGet(context,"#{user.userName}", String.class);
}
You can also try injecting entire user bean and get userName field from it in getter.
With all setters/getters in place, I was having the same problem (null reference to user) because of missing empty constructor in User class.
In the example you provided, the dataBrowser and user beans are instantiated before constructing the table, so referencing #{dataBrowser.userName} should already find the userName #ManagedProperty correctly injected (not being a #PostConstruct problem).
I just came across the same problem, and found out by chance, that it is not working, if I try with firefox (actually icedove under linux), but well working, if I try with the eclipse build-in browser.
Even so this does not make sense to me, have you tried with different browsers already?
michal777's answer is very well working. I have extended it to this:
#ManagedProperty("#{nameBean}")
private NameBean nameBean;
public NameBean getNameBean() { return nameBean; }
public void setNameBean(NameBean nameBean) { this.nameBean = nameBean; }
public NameBean getNameBean_Workaround() {
FacesContext context = FacesContext.getCurrentInstance();
return (NameBean) context.getApplication().evaluateExpressionGet(context,"#{nameBean}", NameBean.class);
}
and later on:
if (nameBean != null) {
nameBean.setName("achsooo");
}
else {
getNameBean_Workaround().setName("achsooo2222");
}
Now, in the eclipse browser "achsooo" gets set, and in icedove "achsooo2222" gets set.
#{user.userName} is interpreted by JSF as getUser().getUserName()
So it is better to have a #ManagedProperty of type User, with its getter/setter methods getUser/setUser. With that you can access the user's name by #{user.userName}.
I had this problem, and the problem was actually twofold. (Note also that #ManagedProperty will only ever work in a #ManagedBean class and if that #ManagedProperty class is of the same or lesser scope (application, session, view, request, etc.).) Here is how I fixed it:
Problem 1: JSF is stupid and doesn't handle #ManagedProperty injection properly in abstract classes.
Solution:
Make every class that uses #ManagedProperty be annotated with #ManagedBean.
Make every abstract class that uses the property not be annotated with #ManagedProperty and instead only provide abstract getter and setter methods that non-abstract classes will each override.
Use the abstract class's getter method instead of the #ManagedProperty itself in abstract classes.
Problem 2: JSF is stupid and doesn't handle #ManagedProperty injection properly in #ManagedBean classes not created by JSF (i.e. you are creating these classes yourself using new).
Solution options:
Let JSF create the class that uses the #ManagedProperty.
Use the following code:
MyClass example = Utils.getELValue("EL Expression Goes Here", MyClass.class);
public static <T> T getELValue(final String elName, final Class<T> clazz) {
FacesContext fc = FacesContext.getCurrentInstance();
return (T) fc.getApplication().getELResolver().getValue(fc.getELContext(), null, elName);
// Potential (untested) alternative:
// ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession().getAttribute("")
}