Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seamfaces 147 - viewActions #64

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from

Conversation

gonzalad
Copy link
Contributor

@gonzalad gonzalad commented Nov 3, 2011

viewAction functionnality in 3 flavors :

  1. Untyped approach (not so CDI like - but dead simple and similar to Seam 2 pages.xml)
    @viewconfig
    public interface ApplicationViewConfig {
    static enum View1 {
    @ViewPattern("/item.xhtml")
    @ViewAction("#{bean.doSomething()}")
    VIEW_ITEM;
    }
    }
  2. Typed - you just need to create your own annotation with @ViewActionBindingTypeQualifier with value pointing to the view enum.
    @viewconfig
    public interface ApplicationViewConfig {
    static enum View1 {
    @ViewPattern("/item.xhtml")
    VIEW_ITEM;
    }
    }

public class ItemAction {
@ViewAction(VIEW_ITEM)
public void loadItem() {
...
}
}

  1. Page Controller
    Just annotate your view enum with a @controller pointing to a CDI managed-bean.
    The managed bean lifecycle methods will automatically be called during this view lifecycle.
    @viewconfig
    public interface ApplicationViewConfig {
    static enum View1 {
    @ViewPattern("/item.xhtml")
    @controller(ItemController.class)
    VIEW_ITEM;
    }
    }
    public class ItemController {
    @before
    @RenderResponse
    public void loadItem() {
    ...
    }
    }

Unit tests and sample application provided.

Functionnality missing in my opinion :

  • Introducing @BeforeAction
    This annotation would be called before a JSF action (whether immediate or not).
    Not 100% sure about its usefulness though.

Bugs / code redundancy :

  • enforce order execution between Restrict annotation and view actions (pb is CDI events aren't ordered).
  • don't like xxxPhase dependency on xxxExtension, should be the other way around
  • findViewsWithPatternsThatMatch and qualifier resolution logic duplicated in ViewConfigStoreImpl and ViewControllerStore (extract into common utility ?)

ViewAction are registered in ViewConfigStore.
Limitation due to ViewConfigStore storing only Annotation.
I need to store at least AnnotatedMethod otherwise I won't be able to know
which method to call if 2 methods have been annotated with exactly the same
annotation (same attribute values I think).
@ViewAction and @ViewActionBindingType usage are as per
https://issues.jboss.org/browse/SEAMFACES-147

@ViewController usage is like MyFaces CODI's @PageBean
(https://cwiki.apache.org/confluence/display/EXTCDI/JSF+Usage#JSFUsage-PageBeans)

Sample usage in seam-faces-example-viewconfig application
Those where shortcut annotations duplicating @Before/@after @RenderResponse
And removed usage of @Before/@after and phase annotation with @ViewAction.
Attribute usage is more explicit here.
@gonzalad
Copy link
Contributor Author

Hello,

Thought a bit about the bugs and code redundancy part.

I had an idea but it would require a bit of refactoring.

Here's the idea :

  • remove ViewControllerDescriptor and ViewControllerStore notion.
  • keep only ViewConfig and ViewConfigStore.
  • add to ViewConfigDescriptor a private List viewActionHandlers.

ViewActionHandler will represents all actions executed during the view processing lifecycle.
There will be only one jsf lifecycle listener which will execute all viewActionHandlers (no more SecurityPhaseListener, SecurityBindingType annotations being handled by a viewActionHandler).

ViewAction will contain :

  • phaseInstant (when during the JSF lifecycle will it be executed).
  • Object execute() (the action itself).

There will be 3 implementations of ViewActionHandler. One of them will be itself generic - a la Hibernate Validator.

First one : SecurityBindingTypeHandler

This will execute a code similar to the actual SecurityPhaseListener.

With this handler there will be a SecurityBindingTypeExtension which will scan all SecurityBindingType annotations and add them to the corresponding ViewConfig#viewActionHandlers.

Second one : ViewActionBindingTypeHandler

Same thing but for ViewActionBinding annotations.

Third one : ViewActionHandler - a la Hibernate Validator

For this one, we need an additional interface : ViewActionHandlerProvider, and an additionnal meta-annotation @ViewAction.

public interface ViewActionHandlerProvider<V extends ViewAction> {
  List<ViewActionHandler> getActionHandlers();
  void initialize(X annotation);
}

There will be one viewActionHandlerProvider per annotation (with a ViewAction binding type annotation) appearing on a view enum.

Sample usage : creating a @BeginConversation view action.

@ViewConfig
public interface MyAppViewConfig {

    static enum Pages {

        @ViewPattern("/item.xhtml")
        @BeginConversation
        ITEM
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ViewAction(BeginConversationHandler.class)
@Begin @ApplyRequestValues
public @interface BeginConversation {
}
public class BeginConversationHandler implements ViewActionHandler<ElViewAction> {
  @Inject
  private Conversation conversation;

  boolean handles(PhaseInstant phaseInstant) {...}

  void initialize(ElViewAction annotation) {...}

  public Object execute() {
    conversation.begin();
    return null;
  }
}

And with a similar logic, we have our ElViewAction (donno how to better name all these interfaces / classes)

What's next ?

My implementation notes are available here : https://gist.github.com/1356107

If you're interested by this approach I can work on it the next or the following week and make another pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant