Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Table of Contents

Table of Contents
indent20px
styledisc
printablefalse

Intro

See Pre-required readings

Further readings:

Usage for Users

ProjectStage

...

In some cases it isn't possible to use CDI based configuration. Esp. for parts which have to be active before the CDI container gets bootstrapped.
For such cases CODI uses an extensible configuration approach. By default it supports configuration via:

  • ServiceLoader (if classes have to be configured which implement an interface or extend an abstract class)
  • System properties
  • JNDI
  • Resource Bundle (properties file with the name myfaces-extcdi.properties btw. /META-INF/myfaces-extcdi.properties)

However, with a custom ConfiguredValueResolver it's possible to resolve configured values from any kind of configuration-source.

Logging

To avoid external dependencies, CODI uses the JDK Logger. However, CDI often requires serializable beans and JDK loggers aren't serializable - therefore CODI provides a serializable wrapper for the JDK Logger.

...


public class MyBean
{
    @Inject
    private Logger logger;
}

If the custom implementation is annotated with @Advanced it's possible to wrap the default implementation for delegating to it. The only requirement is a field called default + the name of the artifact - e.g. defaultViewConfigExtractor . Since such artifacts are used during the bootstrapping process CDI, it isn't possible to use std. CDI based dependency injection.

Logging

To avoid external dependencies, CODI uses the JDK Logger. However, CDI often requires serializable beans and JDK loggers aren't serializable - therefore CODI provides a serializable wrapper for the JDK LoggerBy default the fully qualified class name of the target class which uses the injected logger, will be used to create the logger. As an alternative it's possible to use the LoggerDetails qualifier to provide e.g. a name for the logger.

Code Block
java
java
titleInjectable JDK logger with a custom name
public class MyBean
{
    @Inject
    @LoggerDetails(nameprivate = "AppLogger")
    private Logger logger;
}

Provider

BeanManagerProvider

Logger logger;
}

By default the fully qualified class name of the target class which uses the injected logger, will be used to create the logger. As an alternative it's possible to use the LoggerDetails qualifier to provide e.g. a name for the logger.

Code Block
java
java
titleResolving the Bean-ManagerInjectable JDK logger with a custom name

public class MyBean
{
    @Inject
    @LoggerDetails(name = "AppLogger")
    private Logger logger;
}

Provider

BeanManagerProvider

Code Block
java
java
titleResolving the Bean-Manager

@Inject

@Inject
private BeanManager beanManager;

//or

BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();

...

Code Block
java
java
titleObserving the startup event
@ProjectStageActivated({Development.class, IntegrationTest.class})
public class SampleDataStartupObserver
{
    protected void createSampleData(@Observes StartupEvent startupEvent, UserRepository userRepository)
    {
        User user = new User("Demo", "User");
        userRepository.save(user);
    }
}

Tools

DefaultAnnotation

Type-safe Resource-bundles (since CODI v1.0.1)

The message-module of CODI allows easy, pluggable and therefore advanced message-handling. However, besides messages it's sometimes essential to use resource-bundles in a type-safe manner (e.g. in case of custom configs which don't need be customizable).

Injecting and using a Resource-bundle

@Bundle allows to inject a ResourceBundle. This interface is provided by CODI and is a simpler but injectable version of the std. ResourceBundleFor creating instances of Annotations, you can use the literal trick. A custom implementation allows to provide custom values (see e.g. the NamedLiteral which is used by CODI internally). If you are fine with the default values of an annotation, you can use DefaultAnnotation to create an annotation for a given type, instead of a custom literal implementation.

Code Block
java
java
titleCreate instances of AnnotationsInjecting and using a resource-bundle
CustomAnnotation annotation = DefaultAnnotation.of(CustomAnnotation.class);

Misc

@Advanced

This annotation can be used as marker annotation for artifacts which aren't managed by CDI. If such arifacts are supported by CODI (the documentation of every module shows such artifacts) and annotated with this annotation, it's possible to use dependency injection for fields. Furthermore, this annotation can be used as CDI qualifier.

@Enhanced

This annotation isn't used by CODI modules. It's a common annotation which can be used as marker annotation or qualifier by CODI add-ons. So they don't have to introduce their own marker annotation.

BeanNames

This interface is a marker interface for all interfaces which contain bean names (used by @javax.inject.Named within CODI). So it's very easy to find beans which can be used in EL expressions.

CoreModuleBeanNames

This interface specifies all beans of the core which can be resolved by name.

@InvocationOrder

Artifacts which support this annotation can be sorted. The default order is 1000. Artifacts with a lower ordinal will be called before artifacts with a higher ordinal. If there is an artifact which is supported by CODI but doesn't provide an explicit order, it will be moved at the end of the list.

Base contracts

The following artifacts define base contracts which can be used by CODI modules or any other custom modules which would like to build on the well known contracts provided by CODI.
The information provided by this section is quite general because this part of the Core just specifies a quite abstract contract which is independent of a concrete technology.

Please have a look at the specific modules which use those contracts (esp. the JSF module), if you need more concrete information.

Config/View

This part of the Core provides the basic concepts which allow to provide a type-safe config for views. CODI currently uses it in the JSF module for typesafe navigation as well as multiple inheritance for type-safe page-configs.
ViewConfig as well as DefaultErrorView are the foundations for the concept and will be explained in the documentation of the JSF module. However, it's possible to use it for other UI technologies as well.

@View

This annotation can be used as interceptor to restrict calls to methods to one or more views. Modules are also allowed to use it as marker annotation to link a bean to a view by annotating the bean with it and pointing to the view(s). In this case a module is allowed to store the information internally and remove the interceptor dynamically to avoid performance impacts.

ViewMetaData

This annotation allows to provide custom meta-data. Just annotate a custom annotation with it. A module like the JSF module has to provide a resolver to query it. A query might return multiple results of the same type. If it doesn't make sense to have multiple results, you can use @ViewMetaData(override=true).

...


@Target({TYPE})
@Retention(RUNTIME)
@Documented

@ViewMetaData
public @interface InfoPage
{
}
import org.apache.myfaces.extensions.cdi.core.api.resource.bundle.ResourceBundle;

//...
public class MyBean
{
    @Inject
    //@Jsf //optional to use the current locale
    @Bundle(MyBundle.class)
    private ResourceBundle resourceBundle;

    public String getMyValue()
    {
        return this.resourceBundle.getValue(MyBundle.MyKey.class);
    }
}

By default a resource-bundle class/interface is mapped to the corresponding bundle-file via naming convention. A class/interface can be annotated with @Bundle optionally to find it easier via searching for the annotation or to changing the name and/or package of the corresponding bundle-file.

Code Block
java
java
titleImplementing a resource-bundle

package mypackage.myconfig;

//@Bundle //optional in this case
//Bundle gets mapped to mypackage.myconfig.my_bundle.properties
public interface MyBundle
{
    //mapped to the resource-bundle key (by naming convention): my_key
    public class MyKey implements BundleKey, MyBundle {}

    //mapped to the resource-bundle key (manually): secondKey
    @Named("secondKey")
    public class MyKey2 extends BundleValue implements MyBundle {}
}

Injecting a Resource-bundle value directly

Instead of injecting the resource-bundle and resolving a value by key, it's possible to inject the value directly. That's e.g. useful for configs, because in such cases you are interested in few very specific values.

Code Block
java
java
titleInjecting a resource-bundle value

@Bundle(name = "mypackage.myconfig.mybundle")
public interface MyBundle
{
    //mapped to the resource-bundle key (by naming convention): my_value
    //@Named("myKey") //for mapping it to the resource-bundle key (manually): myKey
    public class MyValue extends BundleValue implements Messages {}
}

//...
public class MyBean

The JSF module of CODI allows to resolve this meta-data via the ViewConfigResolver. Since this resolver is aware of JSF specific concepts, it isn't provided by the Core. Please have a look at the documentation of the JSF module to get further information about it.

Navigation

ViewNavigationHandler

This navigation handler defines how to navigate with view-configs. Currently it's used by all JSF modules to allow implicit navigation based on the view-configs.

Code Block
javajava
titleObserving the navigation

@Model
public class ManualNavigationBean
{
    @Inject
    private ViewNavigationHandlerMyBundle.MyValue viewNavigationHandlermyValue;

    public voidString navigateToHelloMyFacesCodigetMyValue(ActionEvent actionEvent)
    {
        this.viewNavigationHandler.navigateTo(DemoPages.HelloMyFacesCodi.class);
    }

    public void navigateToErrorView(ActionEvent actionEvent)
    {
        this.viewNavigationHandler.navigateTo(DefaultErrorView.classreturn this.myValue.toString();
    }
}

This example is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Since it's a generic concept, it's also possible to provide an implementations for other view-technologies.

PreViewConfigNavigateEvent

Tools

DefaultAnnotation

For creating instances of Annotations, you can use the literal trick. A custom implementation allows to provide custom values (see e.g. the NamedLiteral which is used by CODI internally). If you are fine with the default values of an annotation, you can use DefaultAnnotation to create an annotation for a given type, instead of a custom literal implementationThis event gets triggered if a navigation is going to happen from and to a page represented by a view-config. It also allows to redefine the navigation target.

Code Block
java
java
titleObserving the navigationCreate instances of Annotations
@Model
publicCustomAnnotation class ViewConfigNavigationObserver
{
    @Inject
    //@Jsf //just in case of a JSF application
    private MessageContext messageContext;

    protected void onViewConfigNavigation(@Observes PreViewConfigNavigateEvent navigateEvent)
    {
        if(/*...*/)
        {
            navigateEvent.navigateTo(DefaultErrorView.class);
        }

        this.messageContext.message()
                                .text("navigate from {oldViewId} to {newViewId} view.")
                                .namedArgument("oldViewId", navigateEvent.getFromView())
                                .namedArgument("newViewId", navigateEvent.getToView())
                           .add();
    }
}

In this example the navigation is observed and in a special case the navigation target is changed to the configured default error view. At the end a message gets created and added to the current MessageHandler. In case of a JSF application it gets added to the FacesContext.

This example is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

Scope/Conversation

All interfaces and annotations which are independent from the concrete UI technology are provided by the core. E.g. the concepts of CODI conversations aren't bound to JSF. So the core defines the basic API for CODI conversations. Instead of providing a framework adapter (like MyFaces Orchestra does), CODI hosts the specific implementation in the corresponding module. Currently the UI modules of CODI are just for JSF. However, it would be possible to provide a module e.g. for (plain) servlets. Such a module can use the APIs provided by the core (which are independent of JSF and its concepts).

@ConversationScoped

This isn't the std. CDI annotation!

With this annotation it's possible to scope beans in parallel or grouped conversations which are way more powerful that the std. conversation of CDI 1.

This scope is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@ViewAccessScoped

With this annotation it's possible to save beans until the first request of a new view doesn't access it. It's a very convenient scope e.g. for wizard which can't be interrupted.

This scope is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@WindowScoped

This annotation is comparable to a session per window. Compared to the scopes mentioned above, all beans will be removed at the same point in time.

This scope is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

WindowContext

This context contains all CODI scopes which are bound to a window and allows to control them in a fine-grained manner. Furthermore, it contains information about the current window like the window-id.

annotation = DefaultAnnotation.of(CustomAnnotation.class);

Misc

@Advanced

This annotation can be used as marker annotation for artifacts which aren't managed by CDI. If such arifacts are supported by CODI (the documentation of every module shows such artifacts) and annotated with this annotation, it's possible to use dependency injection for fields. Furthermore, this annotation can be used as CDI qualifier.

@Enhanced

This annotation isn't used by CODI modules. It's a common annotation which can be used as marker annotation or qualifier by CODI add-ons. So they don't have to introduce their own marker annotation.

BeanNames

This interface is a marker interface for all interfaces which contain bean names (used by @javax.inject.Named within CODI). So it's very easy to find beans which can be used in EL expressions.

CoreModuleBeanNames

This interface specifies all beans of the core which can be resolved by name.

@InvocationOrder

Artifacts which support this annotation can be sorted. The default order is 1000. Artifacts with a lower ordinal will be called before artifacts with a higher ordinal. If there is an artifact which is supported by CODI but doesn't provide an explicit order, it will be moved at the end of the list.

Base contracts

The following artifacts define base contracts which can be used by CODI modules or any other custom modules which would like to build on the well known contracts provided by CODI.
The information provided by this section is quite general because this part of the Core just specifies a quite abstract contract which is independent of a concrete technology.

Please have a look at the specific modules which use those contracts (esp. the JSF module), if you need more concrete information.

Config/View

This part of the Core provides the basic concepts which allow to provide a type-safe config for views. CODI currently uses it in the JSF module for typesafe navigation as well as multiple inheritance for type-safe page-configs.
ViewConfig as well as DefaultErrorView are the foundations for the concept and will be explained in the documentation of the JSF module. However, it's possible to use it for other UI technologies as well.

@View

This annotation can be used as interceptor to restrict calls to methods to one or more views. Modules are also allowed to use it as marker annotation to link a bean to a view by annotating the bean with it and pointing to the view(s). In this case a module is allowed to store the information internally and remove the interceptor dynamically to avoid performance impacts.

ViewMetaData

This annotation allows to provide custom meta-data. Just annotate a custom annotation with it. A module like the JSF module has to provide a resolver to query it. A query might return multiple results of the same type. If it doesn't make sense to have multiple results, you can use @ViewMetaData(override=true).

Code Block
java
java
titleCustom Meta-data for View-Configs

@Target({TYPE})
@Retention(RUNTIME)
@Documented

@ViewMetaData
public @interface InfoPage
{
}

The JSF module of CODI allows to resolve this meta-data via the ViewConfigResolver. Since this resolver is aware of JSF specific concepts, it isn't provided by the Core. Please have a look at the documentation of the JSF module to get further information about it.

Navigation

ViewNavigationHandler

This navigation handler defines how to navigate with view-configs. Currently it's used by all JSF modules to allow implicit navigation based on the view-configs.

Code Block
java
java
titleObserving the navigation

@Model
public class ManualNavigationBean
{
    @Inject
    private ViewNavigationHandler viewNavigationHandler;

    public void navigateToHelloMyFacesCodi(ActionEvent actionEvent)
    {
        this.viewNavigationHandler.navigateTo(DemoPages.HelloMyFacesCodi.class);
    }

    public void navigateToErrorView(ActionEvent actionEvent)
    {
        this.viewNavigationHandler.navigateTo(DefaultErrorView.class);
    }
}

This example This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module. Since it's a generic concept, it's also possible to provide an implementation implementations for other view-technologies.

...

PreViewConfigNavigateEvent

This interface allows to close the associated conversation immediately. Furthermore, it's possible to restart the conversation if it is known that it's going to started again soon (the only difference to closing the conversation is a better performance).

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

@ConversationGroup

This annotation allows to group conversations with a type-safe mechanism.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@ConversationRequired

This annotation allows to prevent a navigation to a view which require an existing conversation.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@CloseConversationGroup

This method-interceptor allows to close the conversation(-group) of the current bean or an explicitly specified group after the invocation of the method or in case of a specified exception.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

event gets triggered if a navigation is going to happen from and to a page represented by a view-config. It also allows to redefine the navigation target.

Code Block
java
java
titleObserving the navigation

@Model
public class ViewConfigNavigationObserver
{
    @Inject
    //@Jsf //just in case of a JSF application
    private MessageContext messageContext;

    protected void onViewConfigNavigation(@Observes PreViewConfigNavigateEvent navigateEvent)
    {
        if(/*...*/)
        {
            navigateEvent.navigateTo(DefaultErrorView.class);
        }

        this.messageContext.message()
                                .text("navigate from {oldViewId} to {newViewId} view.")
                                .namedArgument("oldViewId", navigateEvent.getFromView())
                                .namedArgument("newViewId", navigateEvent.getToView())
                           .add();
    }
}

In this example the navigation is observed and in a special case the navigation target is changed to the configured default error view. At the end a message gets created and added to the current MessageHandler. In case of a JSF application it gets added to the FacesContext.

This example is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

Scope/Conversation

...

All interfaces and annotations which are independent from the concrete UI technology are provided by the core. E

ConversationConfig

The conversation config allows to specify e.g. the time-out for grouped conversations and to enable the optional events.

This config is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

WindowContextConfig

The window config allows to specify e.g. the time-out for a window which includes all CODI scopes and to adjust the basic window/-id handling.

concepts of CODI conversations aren't bound to JSF. So the core defines the basic API for CODI conversations. Instead of providing a framework adapter (like MyFaces Orchestra does), CODI hosts the specific implementation in the corresponding module. Currently the UI modules of CODI are just for JSF. However, it would be possible to provide a module e.g. for (plain) servlets. Such a module can use the APIs provided by the core (which are independent of JSF and its concepts).

@ConversationScoped

This isn't the std. CDI annotation!

With this annotation it's possible to scope beans in parallel or grouped conversations which are way more powerful that the std. conversation of CDI 1.

This scope This config is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Scope/Conversation/Event

The following events are optional and have to be activated via the configs mentioned above.

  • AccessBeanEvent
  • CloseConversationEvent
  • CloseWindowContextEvent
  • CreateWindowContextEvent
  • RestartConversationEvent
  • ScopeBeanEvent
  • StartConversationEvent
  • UnscopeBeanEvent

Security

CODI provides some basic hooks to integrate a custom security concept. It isn't related to an existing framework. CODI just allows to integrate such frameworks based on the ViewConfig or via interceptors.

AccessDecisionVoter

This interface is (besides the Secured annotation) the most important part of the concept. Both artifact types are also the only required parts.
This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

The AbstractAccessDecisionVoter allows an easier implementation.

@Secured

...


@Page(navigation = REDIRECT)
public interface Pages extends ViewConfig
{
    @Secured(LoginAccessDecisionVoter.class)
    public interface Secure extends Pages
    {
        public @Page class InternalPage implements Secure {}
    }
}

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@ViewAccessScoped

With this annotation it's possible to save beans until the first request of a new view doesn't access it. It's a very convenient scope e.g. for wizard which can't be interrupted.

This scope is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@WindowScoped

This annotation is comparable to a session per window. Compared to the scopes mentioned above, all beans will be removed at the same point in time.

This scope is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

WindowContext

This context contains all CODI scopes which are bound to a window and allows to control them in a fine-grained manner. Furthermore, it contains information about the current window like the window-id.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

Conversation

This interface allows to close the associated conversation immediately. Furthermore, it's possible to restart the conversation if it is known that it's going to started again soon (the only difference to closing the conversation is a better performance).

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

@ConversationGroup

This annotation allows to group conversations with a type-safe mechanism.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@ConversationRequired

This annotation allows to prevent a navigation to a view which require an existing conversation.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

@CloseConversationGroup

This method-interceptor allows to close the conversation(-group) of the current bean or an explicitly specified group after the invocation of the method or in case of a specified exception.

This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

Scope/Conversation/Config

ConversationConfig

The conversation config allows to specify e.g. the time-out for grouped conversations and to enable the optional events.

This config is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

WindowContextConfig

The window config allows to specify e.g. the time-out for a window which includes all CODI scopes and to adjust the basic window/-id handling.

This config is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Scope/Conversation/Event

The following events are optional and have to be activated via the configs mentioned above.

  • AccessBeanEvent
  • CloseConversationEvent
  • CloseWindowContextEvent
  • CreateWindowContextEvent
  • RestartConversationEvent
  • ScopeBeanEvent
  • StartConversationEvent
  • UnscopeBeanEvent

Security

CODI provides some basic hooks to integrate a custom security concept. It isn't related to an existing framework. CODI just allows to integrate such frameworks based on the ViewConfig or via interceptors.

AccessDecisionVoter

This interface is (besides the Secured annotation) the most important part of the concept. Both artifact types are also the only required parts.
This interface is independent of JSF. However, currently you need the JSF 1.x or 2.x module to use an out-of-the-box implementation of it. Further, details and examples are available in the documentation of the CODI-JSF-module.

Since it's a generic concept, it's also possible to provide an implementation for other view-technologies.

The AbstractAccessDecisionVoter allows an easier implementation.

@Secured

Code Block
java
java
titleSimple usage of @Secured for ViewConfigs

@Page(navigation = REDIRECT)
public interface Pages extends ViewConfig
{
    @Secured(LoginAccessDecisionVoter.class)
    public interface Secure extends Pages
    {
        public @Page class InternalPage implements Secure {}
    }
}

In case of a violation CODI will use the DefaultErrorView as navigation target (if configured).

Code Block
java
java
titleSimple usage of @Secured for ViewConfigs with a special error page

@Page(navigation = REDIRECT)
public interface Pages extends ViewConfig
{
    @Secured(value = LoginAccessDecisionVoter.class, errorView = Login.class)
    public interface Secure extends Pages
    {
        public @Page class InternalPage implements Secure {}
    }
}

In this case the page represented by Login.class with be used instead of the DefaultErrorView.

As an alternative it's possible to use the annotation as interceptor for beans.

Code Block
java
java
titleAlternative usage of @Secured as interceptor

@RequestScoped
@Secured(LoginAccessDecisionVoter.class)
public class SecureBean
{
    //...
}

SecurityViolation

In case of a detected violation a SecurityViolation has to be added to the result returned by the AccessDecisionVoter.

Code Block
java
java
titleSimple example for creating a SecurityViolation

@ApplicationScoped
public class LoginAccessDecisionVoter extends AbstractAccessDecisionVoter
{
    private static final long serialVersionUID = -6332617547592896599L;

    @Inject
    private UserHolder userHolder;

    @Inject
    //@Jsf //only required in combination with the JSF module
    private MessageContext messageContext;

    @Override
    protected void checkPermission(InvocationContext invocationContext, Set<SecurityViolation> violations)
    {
        if(!this.userHolder.isLoggedIn())
        {
            violations.add(newSecurityViolation(this.messageContext.message().text("{msgAccessDenied}").toText()));
        }
    }
}

The rest is done by CODI. Please note that there is a natural overhead if the @Secured annotation is used as interceptor. In combination with the JSF module, we recommend to us it for the ViewConfig instead of beans because the performance overhead is minimal compared to an interceptor.

@Secured and Stereotypes (since CODI v1.0.4)

If there are multiple AccessDecisionVoter and maybe in different constellations, it's easier to provide an expressive CDI stereotypes for it. Later on that also allows to change the behaviour in a central placeIn case of a violation CODI will use the DefaultErrorView as navigation target (if configured).

Code Block
java
java
titleSimple usage Stereotype support of @Secured for ViewConfigs with a special error page

@Page(navigation = REDIRECT)
public interface Pages extends ViewConfig
{
    @Secured(value = LoginAccessDecisionVoter.class, errorView = Login.class)
    public interface Secure extends Pages
    {
        public @Page class InternalPage implements Secure {}
    }
}

In this case the page represented by Login.class with be used instead of the DefaultErrorView.


@Named
@Admin
public class MyBean implements Serializable
{
  //...
}

//...
@Stereotype
@Secured(RoleAccessDecisionVoter.class)
public @interface Admin
{
} 

Furthermore, it's possible to provide custom meta-data easilyAs an alternative it's possible to use the annotation as interceptor for beans.

Code Block
java
java
titleAlternative usage Stereotype of @Secured as interceptorwith custom meta-data
@RequestScoped@Named
@Secured(LoginAccessDecisionVoter.class@Admin(securityLevel=3)
public class SecureBeanMyBean implements Serializable
{
    //...
}

SecurityViolation

In case of a detected violation a SecurityViolation has to be added to the result returned by the AccessDecisionVoter.

Code Block
javajava
titleSimple example for creating a SecurityViolation


//...
@Stereotype
@Secured(RoleAccessDecisionVoter.class)
public @interface Admin
{
  int securityLevel();
}

@ApplicationScoped
public class LoginAccessDecisionVoterRoleAccessDecisionVoter extendsimplements AbstractAccessDecisionVoterAccessDecisionVoter
{
    private static final long serialVersionUID = -6332617547592896599L;

    @Inject
 8007511215776345835L;
   private UserHolder userHolder;

    @Inject
    //@Jsf //only required in combination with the JSF module@Inject
    private MessageContextAccessDecisionVoterContext messageContextvoterContext;

    @Override
public    protected void Set<SecurityViolation> checkPermission(InvocationContext invocationContext, Set<SecurityViolation> violations)
    {
         if(!this.userHolder.isLoggedIn())Admin admin = voterContext.getMetaDataFor(Admin.class.getName(), Admin.class);
        {
            violations.add(newSecurityViolation(this.messageContext.message().text("{msgAccessDenied}").toText()))int level = admin.securityLevel();
        }//...
    }
}

...

 

BeanCreationDecisionVoter

...