These slides show how to use type-safe mechanisms provided by MyFaces CODI for developing JSF applications which are more type-safe and easier to maintain.
http://2012.con-fess.com/sessions/-/details/136/MyFaces-CODI-and-JBoss-Seam3-become-Apache-DeltaSpike is the next part with more details about MyFaces CODI and Apache DeltaSpike at
3. Agenda
• Type-safety
• CODI in a Nutshell
• CODI Setup
• CODI Core
• CODI JSF-Module
• CODI Message-Module
• CODI JPA-Module
• CODI Bean-Validation
• CODI Scripting-Module
• Integration and Unit Tests with CODI
4. Type-safety - Why should we care about it?
• Allows to use std. IDE features like auto-completion
• Specialized IDE support is always behind
• No Typos
• Several features allow compile-time or at least startup checks
• Easier for new developers to find usages
• Easier refactorings
• Easier maintenance
• …
5. MyFaces CODI - Overview
• MyFaces Extensions CDI aka MyFaces CODI is a
portable CDI extension which can be used with
Apache OpenWebBeans, JBoss Weld,… and
in combination with other portable CDI extensions
• CODI-Core is required in any case
• Modules
– JSF Module (for 1.2 and 2.0 and 2.1)
– JPA Module
– BV Module
– I18n-Message Module
– Scripting Module
– Test Support Modules
6. MyFaces CODI in a Nutshell
• JSF 1.2 and 2.x • Type-safe View-Configs
• Type-safety • Type-safe Navigation
• Extensibility • JPA Integration
• Advanced Scopes • Dependency Injection
• Various Events Support for BV
• View-Controller • Advanced I18n
• JSF 2 Scope Mappings • Scripting Integration
• And more!
8. Getting CODI up and running
• Add CODI to the project
– With Maven
• Add the modules (or the all-in-one package) to the POM
– Without Maven
• Download the current dist package
• Add the modules (or the all-in-one package) to the Classpath of
the project
• Start using it!
9. Getting CODI up and running - Hints
• With JEE 5 and Mojarra use the controlled bootstrapping
add-on
• Attention (hint for all bean archives):
Ensure that the libs aren’t duplicated – otherwise the CDI
implementation will blame ambiguous interceptors, beans,…
11. Startup*
• Startup-Observer for the StartupEvent
Triggered after the environment is initialized
– Initialization tasks which need an up and running environment
– Easy logging that the module was started
protected void logModuleStart(
@Observes StartupEvent startupEvent) {
...
}
• StartupEventBroadcaster
Allows to integrate custom broadcasting mechanisms before
the first mechanism of CODI gets called
12. ProjectStage and ProjectStageActivated
• Configure beans for a special project-stage in a type-safe way
• Examples
– Sample data
– Debug Phase-Listener
@ProjectStageActivated(
ProjectStage.Development.class)
public class SampleDataStartupObserver {
protected void createSampleData(
@Observes StartupEvent startupEvent,
UserRepository userRepository) {
//...
userRepository.save(user);
}
}
13. Custom Project-Stages - 1
public class ProjectStages
implements ProjectStageHolder {
@Typed() //no bean!
public static final class CustomProjectStage
extends ProjectStage {}
public static final CustomProjectStage
CustomProjectStage =
new CustomProjectStage();
}
+ Service-Loader config
14. Custom Project-Stages - 2
• Configure the project-stage like std. CODI project stages
– JSF std. project stage
– org.apache.myfaces.extensions.cdi.ProjectStage
– ConfiguredValueResolver
• Injecting the current project-stage
@Inject private ProjectStage projectStage;
• Compare the injected value
ProjectStage.Development.equals(this.projectStage)
• Overrule the current project-stage manually
ProjectStageProducer.setProjectStage(
ProjectStages.CustomProjectStage)
15. [CODI-Hint] Deactivatable
• CDI allows deactivation via a veto-mechanism
• Won‘t work for artifacts which aren‘t managed by CDI
• CODI allows do deactivate such implementations which
implement Deactivatable
• Deactivating classes via an implementation of
ClassDeactivator (+ Service-Loader config)
17. @JsfPhaseListener
@ProjectStageActivated(
ProjectStage.Development.class,
CustomProjectStage.Debugging.class)
@Advanced
@JsfPhaseListener
public class DebugPhaseListener implements PhaseListener {
@Inject
private Logger logger;
public void beforePhase(PhaseEvent phaseEvent) {
this.logger.info("before " + phaseEvent.getPhaseId());
}
public void afterPhase(PhaseEvent phaseEvent) {
this.logger.info("after " + phaseEvent.getPhaseId());
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}
18. @InvocationOrder
• Allows to specify the order of multiple artifacts
• Example
@JsfPhaseListener
@InvocationOrder(1) //optional
public class DebugPhaseListener
implements PhaseListener {
//...
}
20. CODI View-Configs and @Page
• Allow to
– host meta-data for pages
– structure pages
– navigate in a type-safe way
• Inline usage at page-beans is possible with restrictions
• Example for index.xhtml
@Page
public class Index implements ViewConfig {}
21. Organizing your pages
• Meta-data gets inherited
(multiple inheritance with interfaces)
• Nested classes for defining the view-id via convention
(explicit configuration is also possible)
• Example for /pages/index.xhtml
@Page(navigation = REDIRECT)
public interface Pages extends ViewConfig {
public @Page class Index implements Pages {
}
}
22. Inherit Page-Configs by Example
@Page(navigation = REDIRECT)
public interface Pages extends ViewConfig {
public @Page class Login
extends DefaultErrorView implements Pages {}
}
23. Type-safe Navigation
• View-Conig
public Class<? extends Pages> register() {
//...
return Pages.Login.class;
}
• ViewNavigationHandler (for manual navigation)
@Inject
private ViewNavigationHandler vnh;
vnh.navigateTo(Pages.Login.class);
• Navigation Event (PreViewConfigNavigateEvent)
Allows to observe type-safe navigations and change the
navigation target
24. @Secured by Example
@Secured(LoginAccessDecisionVoter.class)
public interface Secure extends Pages {
@PageBean(FeedbackPage.class)
public @Page class FeedbackList implements Secure {}
}
@ApplicationScoped
public class LoginAccessDecisionVoter extends
AbstractAccessDecisionVoter {
@Override
protected void checkPermission(
InvocationContext ic, Set<SecurityViolation> violations) {
if(...) {
violations.add(newSecurityViolation("access denied"));
}
}
}
25. View-Controller
• Via
– View-Config (@PageBean)
– Inline (@View)
– Package based
• @Page for Page-Beans
• @InlineViewConfigRoot as marker
• Annotations
– @InitView
– @PrePageAction
– @PreRenderView
– @PostRenderView
27. Error-Pages
• Configure a default error page
• Security violations default error page
(or the explicitly configured page)
• Manual Navigation to the default error view
(independent of the configured error page)
@Inject
private ViewNavigationHandler vnh;
vnh.navigateTo(DefaultErrorView.class);
28. Type-save Config by Example
@Specializes
public class CustomJsfModuleConfig
extends JsfModuleConfig {
@Override
public boolean isAlwaysKeepMessages () {
return false;
}
}
With Weld you have to use @Alternative + xml config
29. Custom View-Meta-data
• Allows to create custom meta-data
• Get the meta-data with:
ViewConfigResolver
#getViewConfigDescriptor(...)#getMetaData();
• Example
@Target({TYPE})
@Retention(RUNTIME)
@Documented
@ViewMetaData
public @interface AppInfo { ... }
@AppInfo
public @Page class About implements Pages {}
31. I18n – The Message-Module
• Highly customizable
• Easy fluent API
• Different argument formats
– Numbered
– Named
– EL-Expressions (optional)
• Serializable (key + config instead of the final message)
other users get the persisted message in their specific language
• Message-Payload (e.g. MessageSeverity)
• Different message sources
• Optimized for JSF (in combination with the JSF Module)
35. @Transactional
• Alternative to EJBs esp. outside an Application-Server
• Allows to customize the behaviour
• Supports multiple persistence-units with qualifiers
40. Bean-Validation by Example - 1
@Inject @Advanced
private Validator validator;
//...
validator.validate(user);
//...
@UniqueLoginName
public class User extends AbstractEntity
{
//...
}
41. Bean-Validation by Example - 2
@Target({TYPE}) @Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {
UniqueLoginNameValidator.class})
public @interface UniqueLoginName {
}
@Dependent
public class UniqueLoginNameValidator
extends ClassLevelValidator
<UniqueLoginName, User> {
@Inject
private UserRepository userRepository;
}
45. CODI and JUnit by Example
@RunWith(JUnit4.class)
public class SimpleTestCase extends AbstractJsfAwareTest {
@Inject private RegistrationPage registrationPage;
@Inject private UserRepository repository;
@Test public void testRegistration() {
User user = this.registrationPage.getUser();
user.setUserName("gp");
user.setFirstName("Gerhard");
//...
assertEquals(Pages.Login.class,
this.registrationPage.register());
assertEquals("Gerhard",
this.repository.loadUser("gp").getFirstName());
}
}
47. CODI and Cargo by Example
@RunWith(JUnit4.class)
public class SimpleTestCase
extends AbstractContainerAwareCargoTest {
@Test
public void testSimpleForm() {
SimplePageInteraction pageInteraction =
new SimplePageInteraction(getTestConfiguration())
.start(Pages.Index.class)
.useDefaultForm();
String inputId = "userName";
pageInteraction.setValue(inputId, "gpetracek")
.clickOk()
.checkState(Pages.Result.class);
}
}