1

In the past I used a lot of getter and setter methods to move as much boolean logic as possible from facelet files to JSF backing beans. This way, the interface of a view was given by the getter and setter methods of its backing bean as well as by the action methods of the backing bean. An advantage of this approach is that the facelet files are rather logic-free and ,therefore, all logic is within the backing beans and can be unit tested.

But with EL 2.2 another programming style became possible. In EL 2.2 you can invoke methods with expressions like

#{bean.collection.size()},
#{bean.collection.add(elem)},
#{bean.property.substring(0, bean.property.indexOf(something))}.

Is the usage of rather complex expressions like parameterized method invocations good style now or do you rather advise against using such expressions? Is there a rule of thumb when to use the new method invocation expressions and when not?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
hwaltz
  • 15
  • 3

3 Answers3

3

The major guideline is the following: reduce as much 'model' logic from the view as possible and leave only the 'view' logic. EL 2.2 made possible some model simplification and reduced the need for creation of artificial properies of JSF beans. Invocation of methods with parameters also enables to pass the necessary information from the view to the controller which would be tedious without that opportunity.

You can call arbitrary methods to access the model from the view that the view part relies on, but you should never call methods that modifies the model from the view.

Let me elaborate on that.

Some legal examples:

  1. evaluate non-accessor methods when building view:
    • render UI components based on some conditions like rendered="#{request.isUserInRole('administrator')}";
    • make collection modifications where necessary like <ui:repeat value="#{bean.set.toArray()}" ... >
    • conditionally evaluate UI component / HTML element attributes like class="#{bean.name.contains('special') ? 'special' : ''}";
    • output non-accessor data like there are #{bean.list.size()} elements.
  2. pass information to the controller in action methods or listeners:
    • execute action methods with currently iterated variables like var="data" and action="#{bean.action(data)}" with public String action(Data data);
    • pass additional data, like current iteration index, in listeners like varStatus="status" and actionListener="#{bean.action(status.index)}" with public String action(int index).

Some to-be-avoided examples:

  1. use EL operators when possible:
    • use #{not empty bean.list} instead of #{bean.list.size() gt 0}.
  2. use method call with parameters instead of extending the model:
    • use #{bean.name.contains('special')} instead of #{bean.special} with public boolean isSpecial() {return name.contains("special");}.
  3. prefer leaving view logic in view for plain rendering of the right things and create model logic in case it applies purely to the model:
    • in case you need to perform some calculations to change the appearance of an object, do that in view directly without changing the model, in case some property is inherent to the model itself, introduce it directly in the model and refer to it from the view.

Some illegal examples:

  1. modify the model from the view:
    • do not use EL 2.2 possibility of calling methods with parameters to break the MVC paradigm, i.e. do not call #{bean.list.add(element)} from the view side.

Of course, all things said apply to the cases that your goals don't contain targeting at the older servers without EL 2.2 support.

As a bigger picture, I'd recommend to also see BalusC's explanation of what MVC architecture represents within the context of JSF.

Community
  • 1
  • 1
skuntsel
  • 11,624
  • 11
  • 44
  • 67
  • Care to expand on the "illegal" bit? Since in JSF [you don't implement a controller](http://stackoverflow.com/questions/10111387/understanding-jsf-as-a-mvc-framework), the view *has* to modify the model. – mabi Dec 11 '13 at 10:08
  • 1
    @mabi: what a controller is, depends on point of view: http://stackoverflow.com/questions/5104094/what-components-are-mvc-in-jsf-mvc-framework/5104604#5104604 – BalusC Dec 11 '13 at 10:24
  • 1
    @mabi Within JSF the front controller 'shares' some of the reponsibilities with managed beans, namely action methods and action/ajax listeners. You can see them as being called from the front controller as part of its job that's done via managed bean methods. The other part of the managed bean is the model that's typically done as composition, i.e. as the bean properties. – skuntsel Dec 11 '13 at 10:29
  • @BalusC Yeah, but since the term MVC has different view-points, I don't buy it as the sole reason for why I shouldn't do this. If it's a business process, you still need the backing bean/services to perform a multi-step algorithm. – mabi Dec 11 '13 at 10:32
  • 1
    Oh, `#{bean.string.replace('old', 'new')}` is a bad example as it doesn't modify the model. @mabi: the view should merely access the model, not modify it. The controller (the managed bean instance) is the only one responsible for that. Otherwise the model is tight coupled into the view and you can't add for example loggers/interceptors/pre-postprocessing, etc. – BalusC Dec 11 '13 at 10:37
  • @BalusC Yeah, immutability, immutability! I tried to broaden the perspective and ended up in this set of examples. There are possibly many more cases to be considered, so maybe someday we'll extend this list. – skuntsel Dec 11 '13 at 10:41
0

Personally, i prefer using "complex" EL expressions when really needed, and take any bit logic/traitement to the correspondant managed-beans.
For example: the first example you put is the only one that i may sometimes use directly, the two others however should be for me put in action methods with void/String returning type according to the need.

Omar
  • 1,430
  • 1
  • 14
  • 31
0

Use El 2.2 to reduce our JSF code, e.g. setPropertyActionListener is made redundant, see JSF Core Tag :setPropertyActionListener vs attribute vs param

Community
  • 1
  • 1
rwitzel
  • 1,694
  • 17
  • 21