View Controllers and Navigation
While part1 showed us how we can do managed beans in Javascript, we now will go a little bit deeper. In this part we will talk about view controllers and navigation implemented in Scala.Short Introduction to ViewControllers
While JSF does not know the ViewController pattern, for JSF is everything a managed bean, it makes sense to name a certain set of managed beans ViewControllers.Per definition in JSF a ViewController is a managed bean, which deals directly with the user interface interaction from the backend.
Such interactions are
- Actions
- Events
- Listeners
- etc...
A typical plain Java Viewcontroller
So a typical Java ViewController in a plain JSF environment looks like following.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ManagedBean | |
@RequestScoped | |
public class TestViewController implements Serializable { | |
private static final String PAGE2 = "page2"; | |
private static final String PAGE3 = "page3"; | |
String value1 = ""; | |
String value2 = ""; | |
public String action1() { | |
return PAGE2; | |
} | |
public String action2() { | |
return PAGE3; | |
} | |
public void actionListener(ActionEvent myAction) { | |
//do something here | |
} | |
public String getValue1() { | |
return value1; | |
} | |
public void setValue1(String value1) { | |
this.value1 = value1; | |
} | |
public String getValue2() { | |
return value2; | |
} | |
public void setValue2(String value2) { | |
this.value2 = value2; | |
} | |
} |
Sidenote: there are frameworks which add dedicated view controllers with dedicated callbacks for postCreate, preRender
ViewController in Scala
The question now is, how does this look in Scala.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object TestViewController { | |
val PAGE1 = "page1" | |
val PAGE2 = "page2" | |
} | |
@ManagedBean | |
@RequestScoped | |
@serializable | |
class TestViewController { | |
import TestViewController._ | |
var value1: String = "" | |
var value2: String = "" | |
def action1():String = PAGE1 | |
def action2():String = PAGE2 | |
def actionListener(myAction: ActionEvent) { | |
//Do something here | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object TestViewController { | |
val PAGE1 = "page1" | |
val PAGE2 = "page2" | |
} |
So what is this object all about?
Scala does neither know static classes nor variables, instead it has singletons in its language core as companion pattern to classes. If a construct is defined via object instead of class, then the resulting object is a singleton. To make the code tighter, Scala also allows imports everywhere. Members of singletons can be imported simply by import <Singleton>._ so that we can call them directly in our code.
If you notice in our action callbacks we return the members of the singleton directly, like we would do it with static variables in Java.
MyFaces Codi Typesave Navigation
MyFaces Codi has an interesting feature, the so called typesave implicit navigation.While JSF2 already eased the lives of developers by introducing an implicit navigation (aka return value of an action == page name if no navigation rule is given), MyFaces Codi goes one step further.
It maps pages to classes (page name must be the class name) and it allows the grouping of navigation elements in wrapper classes (follow this link for further reference).
While in my personal opinion, the class based navigation alone, it really shines once you add advanced codi features to it like the security handling or the View Controller extensions.
(For more Information please consult the MyFaces Codi documentation)
Here is a small example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Wizard extends ViewConfig | |
{ | |
@Page | |
public final class Page1 implements Wizard | |
{ | |
} | |
@Page | |
public final class Page2 implements Wizard | |
{ | |
} | |
} | |
@ManagedBean | |
public final class Login | |
{ | |
public Class<? extends ViewConfig> goPage1() { | |
return Page1.class; | |
} | |
} |
- the first one points to /Wizard/Page1
- the second one points to /Wizard/Page2
- We don't have interfaces, we have mixins, but they do not map straight to the structures we need
- the interface classes are the same problem as the interfaces
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Wizard extends ViewConfig { | |
@Page | |
object Page1 extends ViewConfig | |
@Page | |
object Page2 extends ViewConfig | |
def GO_PAGE1: Class[_] = Page1.getClass | |
def GO_PAGE2: Class[_] = Page2.getClass | |
} | |
@ManagedBean | |
class Login { | |
import Wizard._ | |
def goPage1(): Class[_] = GO_PAGE1 | |
} |
That sums up part2 for now
Next week, I will talk about how to leverage Scalas very powerful trait feature to isolate common behavior.
Keine Kommentare:
Kommentar veröffentlichen