Seam event
The seam component model is usedEvent-driven applicationsProgramDeveloped, especially in a fine-grained event model, for the development of fine-grained loose coupling components. Seam events have several types, most of which we have seen:
All these events are mapped to the seam component by binding the JSF El method of the expression. JSF events are defined in the JSF template:
<H: commandbutton value = "Click me! "Action =" # {helloworld. sayhello} "/>
The conversion events of jbpm are specified in the jbpm process definition or page flow definition:
<Start-Page name = "hello" View-id = "/hello. JSP "> <transition to =" hello "> <action expression =" # {helloworld. sayhello} "/> </transition> </start-page>
You can find more information about JSF events and jbpm events elsewhere. We are now focusing on the two new types of events defined by seam.
5.1.1. Page Actions
The page action of seam refers to the event that occurs before the page is rendered. InA WEB-INF/pages. xmlDeclare Page Actions. We can define a page action for any special JSF view ID:
<Pages> <page view-id = "/Hello. jsp" Action = "# {helloworld. sayhello}"/> </pages>
Alternatively, we can use a wildcard*AsView-IDTo specify an action and apply it to all view IDs in this mode:
<Pages> <page view-id = "/Hello/*" Action = "# {helloworld. sayhello}"/> </pages>
If the page action with multiple wildcards matches the current view-ID, seam calls all the actions in the most general-to-special order.
The page action method returns a JSF result. If this result is not empty, seam uses the defined navigation rules to navigate to a view.
In addition<Page>The view ID mentioned in does not need to correspond to a real JSP or facelets page! Therefore, we can regenerate the traditional action-oriented framework functions, just as struts or webwork uses Page Actions. For example:
Todo: translate struts action into page action
This is useful if you want to perform complex tasks (such as http get requests) on Non-faces requests.
You can use<Action>Tag:
<Pages> <page view-id = "/hello. JSP "> <action execute =" # {helloworld. sayhello} "If =" # {not validation. failed} "/> <action execute =" # {hitcount. increment} "/> </Page> </pages>
5.1.1.1. Page Parameters
A jsf faces request (Form submission) simultaneously encapsulates an "action Action" (a method binding) and multiple parameters (input value binding ). A page action may also require parameters!
Because GET requests can be marked, page parameters are passed as request parameters that are easy to read. (Unlike the JSF form input, nothing is readable !)
You can use page parameters without any action methods.
5.1.1.1.1. Map request parameters to the model
Seam allows us to provide a value binding to map a named request parameter to the attributes of a model object.
<Pages> <page view-id = "/hello. JSP "Action =" # {helloworld. sayhello} "> <Param name =" firstname "value =" # {person. firstname} "/> <Param name =" lastname "value =" # {person. lastname} "/> </Page> </pages>
<Param>The Declaration is bidirectional, just like binding a JSF input value:
When a non-faces (get) request of the view ID occurs, seam sets the value of the named request parameter on the model object after the corresponding type change is executed.
Any<S: link>Or<S: button>Transparently or automatically include parameters contained in the request. The value of the parameter is in the rendering phase (when<S: link>Rendered.
Use<Redirect/>Any navigation rule to view ID obviously contains request parameters. The value of the parameter is determined by the value binding size at the end of the call application stage.
This value is obviously propagated by any JSF page submitted with a view ID. This means that the view parameters behave like the faces request'sPageThe context variables are the same in the range.
The ideal scenario isRegardlessFrom what page do we go/Hello. jsp(Or from/Hello. jspBack/Hello. jsp), The value of the referenced model attribute in the value binding should be "remembered", without the need to store conversations (or other server-side states ).
5.1.1.1.2. propagation Request Parameters
If you only specifyNameAttribute, then the request parameters will usePageContext propagation (it is not mapped to model attributes ).
<Pages> <page view-id = "/hello. JSP "Action =" # {helloworld. sayhello} "> <Param name =" firstname "/> <Param name =" lastname "/> </Page> </pages>
If you want to create a multi-layer complex crud page, passing page parameters is particularly useful. You can use it to "remember" The page you previously visited (for example, when you press the Save button) and the entity you are editing.
Obviously, if the parameter is a page parameter of the view<S: link>Or<S: button>Request Parameters are propagated.
This value is obviously transmitted by any JSF page form submission on the page with the specified view ID. (This means that view parameters behave like faces requests.PageIn-range view parameters are the same .)
All of this sounds complicated. You may wonder if such an external structure is really worth your effort. In fact, once you "master it", it is natural to have such an idea. It takes time to understand these materials. Page parameters are the most elegant way to spread States across non-faces requests. The problem of searching the screen is particularly effective when you use a printable result page. In this case, we like to write applications.CodeUse the same code segment to process post and GET requests. The page parameters eliminate the repeated list of Request Parameters in the view definition, and make code implementation easier for redirection.
5.1.1.1.3. conversion and verification
You can specify a JSF converter for complex model attributes:
<Pages> <page view-id = "/calculator. JSP "Action =" # {calculator. calculate} "> <Param name =" X "value =" # {calculator. LHS} "/> <Param name =" Y "value =" # {calculator. RHS} "/> <Param name =" op "converterid =" com. my. calculator. operatorconverter "value =" # {calculator. OP} "/> </Page> </pages>
Or:
<Pages> <page view-id = "/calculator. JSP "Action =" # {calculator. calculate} "> <Param name =" X "value =" # {calculator. LHS} "/> <Param name =" Y "value =" # {calculator. RHS} "/> <Param name =" op "converter =" # {operatorconverter} "value =" # {calculator. OP} "/> </Page> </pages>
JSF validators andRequired = "true"It can also be used as follows:
<Pages> <page view-id = "/blog.xhtml"> <Param name = "date" value = "# {blog. date} "validatorid =" com. my. blog. pastdate "required =" true "/> </Page> </pages>
Or:
<Pages> <page view-id = "/blog.xhtml"> <Param name = "date" value = "# {blog. date} "validator =" # {pastdatevalidator} "required =" true "/> </Page> </pages>
In a better way, the model-based hibernate validator annotation is automatically recognized and verified.
When the type conversion or verification failsFacesmessageWill be addedFacescontext.
5.1.1.2. Navigation
You can useFaces-config.xmlStandard JSF navigation rules defined in. However, JSF navigation rules also have many annoying restrictions:
During redirection, it is impossible to specify a request parameter to be used.
It is impossible for a rule to start or end a conversation.
The rule is operated by obtaining the return value for the action method. It is impossible to give an arbitrary El expression a value.
The deeper problem lies in the logic of "management" inPages. xmlAndFaces-config.xmlIs scattered. It is best to unify this logicPages. xml.
This JSF navigation rule:
<Navigation-Rule> <from-View-ID>/editdocument.xhtml </from-View-ID> <navigation-case> <from-Action >#{ revoke enteditor. update} </from-Action> <from-outcome> success </from-outcome> <to-View-ID>/viewdocument.xhtml </to-View-ID> <redirect/> </navigation-case> </navigation-Rule>
You can rewrite it as follows:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "> <rule if-outcome =" success "> <redirect view-id ="/viewdocument.xhtml "/> </Rule> </navigation> </Page>
If we do not need to use the return value of the character type (JSF result) for contaminationDocumenteditorComponents will be better. Therefore, seam allows us to write:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "evaluate =" # {incluenteditor. errors. size} "> <rule if-outcome =" 0 "> <redirect view-id ="/viewdocument.xhtml "/> </Rule> </navigation> </Page>
Or you can even write it as follows:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "> <Rule If =" # {extends enteditor. errors. empty} "> <redirect view-id ="/viewdocument.xhtml "/> </Rule> </navigation> </Page>
The first form calculates a value binding to determine the result value to be used by a series of navigation rules. The second method ignores the results and calculates the value binding for each possible rule.
Of course, when an update is successful, we may want to end the current conversation. We can do this:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "> <Rule If =" # {extends enteditor. errors. empty} "> <End-conversation/> <redirect view-id ="/viewdocument.xhtml "/> </Rule> </navigation> </Page>
Since we have terminated the session, no subsequent request can tell which document we are interested in. We can pass the Document ID as a request parameter, which also makes the view printable:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "> <Rule If =" # {extends enteditor. errors. empty} "> <End-conversation/> <redirect view-id ="/viewdocument.xhtml "> <Param name =" entid "value =" too many enteditor.doc umentid} "/> </redirect> </Rule> </navigation> </Page>
In JSF, null is a special result. The result null is interpreted as "re-display page ". The following navigation rules match any non-null resultsNon-conformingNull result:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "> <rule> <render view-id ="/viewdocument.xhtml "/> </Rule> </navigation> </Page>
If the result shows null and you want to perform the navigation, use the following format:
<Page view-id = "/editdocument.xhtml"> <navigation from-action = "# {export enteditor. update} "> <render view-id ="/viewdocument.xhtml "/> </navigation> </Page>
View-ID can be provided as a JSF El expression:
<Page view-id = "/editdocument.xhtml"> <navigation if-outcome = "success"> <redirect view-id = "/# {useragent}/displaydocument.xhtml"/> </ navigation> </Page>
5.1.1.3. fine-grained file for navigation definition, Page Actions, and parameters
If you have many different Page Actions and page parameters, or even many navigation rules, you will want to separate these declarations into multiple files. You canCalc/calculator. Page. xmlIs a resource with a view ID/Calc/calculator. jspThe page defines the action and parameters. In this example, the root element is<Page>Element, which implies the view ID:
<Page action = "# {calculator. calculate} "> <Param name =" X "value =" # {calculator. LHS} "/> <Param name =" Y "value =" # {calculator. RHS} "/> <Param name =" op "converter =" # {operatorconverter} "value =" # {calculator. OP} "/> </Page>
5.1.2. component-driven events
The seam component can interact with each other through simple calls between methods. The status component even implements the observer/observable mode. However, when components call each other's methods directly, seam providesComponent-driven events.
InComponents. xmlSpecifies the event listener (observer ).
<Components> <event type = "hello"> <action execute = "# {hellolistener. sayhelloback} "/> <action execute =" # {logger. loghello} "/> </event> </components>
Here,Event TypeIs any string.
When an event occurs, the registered actions of the event followComponents. xmlIs called in sequence. How does a component initiate an event? Seam provides a built-in component.
@ Name ("helloworld") public class helloworld {public void sayhello () {facesmessages. instance (). Add ("Hello world! "); Events. instance (). raiseevent (" hello ");}}
Or you can use annotations.
@ Name ("helloworld") public class helloworld {@ raiseevent ("hello") Public void sayhello () {facesmessages. instance (). Add ("Hello world! ");}}
Note that this event generator does not depend on any event consumer. The event listener can now be implemented completely without relying on the generator:
@ Name ("hellolistener") public class hellolistener {public void sayhelloback () {facesmessages. instance (). Add ("Hello to you too! ");}}
InComponents. xmlTo map events to consumers. If you do not likeComponents. xmlThe set in the file can be replaced by Annotations:
@ Name ("hellolistener") public class hellolistener {@ observer ("hello") Public void sayhelloback () {facesmessages. instance (). Add ("Hello to you too! ");}}
You may want to know why nothing about event objects is mentioned in this discussion. In seam, the event object does not need to be transmitted between the event producer and the listener. The status is retained in the seam context and shared among components. However, if you really want to pass the event object, you can:
@ Name ("helloworld") public class helloworld {private string name; Public void sayhello () {facesmessages. instance (). add ("Hello world, my name is #0. ", name); events. instance (). raiseevent ("hello", name );}}
@ Name ("hellolistener") public class hellolistener {@ observer ("hello") Public void sayhelloback (string name) {facesmessages. instance (). Add ("hello #0! ", Name );}}
5.1.3. Context events
Seam defines many built-in events that can be used by applications for special types of framework integration. These events are:
-
Org. JBoss. seam. validationfailed-Called when JSF verification fails
Org. JBoss. seam. noconversation-No long-running dialog is called when a running or long-running dialog is requested
-
Org. JBoss. seam. presetvariable. <Name>-Call when setting the context variable <Name>
-
Org. JBoss. seam. postsetvariable. <Name>-Call when setting the context variable <Name>
-
Org. JBoss. seam. preremovevariable. <Name>-Called when the context variable <Name> is not set
-
Org. JBoss. seam. postremovevariable. <Name>-Called when the context variable <Name> is not set
-
Org. JBoss. seam. predestroycontext. <scope>-Called before the <scope> context is destroyed
-
Org. JBoss. seam. postdestroycontext. <scope>-Called after the <scope> context is destroyed
-
Org. JBoss. seam. beginconversation-Called when a long running dialog starts
-
Org. JBoss. seam. endconversation-Called when a long running dialog ends
Org. JBoss. seam. beginpageflow. <Name>-Called at the beginning of page stream <Name>
-
Org. JBoss. seam. endpageflow. <Name>-Called at the end of the page stream <Name>
-
Org. JBoss. seam. CreateProcess. <Name>-Called when creating a process <Name>
-
Org. JBoss. seam. endprocess. <Name>-Called at the end of the process <Name>
-
Org. JBoss. seam. initprocess. <Name>-Called when the process <Name> is associated with the Dialog
-
Org. JBoss. seam. inittask. <Name>-Called when the task <Name> is associated with the Dialog
-
Org. JBoss. seam. starttask. <Name>-Called at the beginning of the task <Name>
-
Org. JBoss. seam. endtask. <Name>-Called when the task <Name> is terminated
-
Org. JBoss. seam. postcreate. <Name>-Called when creating a component <Name>
Org. JBoss. seam. predestroy. <Name>-Called when the component <Name> is destroyed
-
Org. JBoss. seam. beforephase-Called before the start of a JSF phase
-
Org. JBoss. seam. afterphase-Call after the end of a JSF stage
-
Org. JBoss. seam. postinitialization-Called when seam is initialized and all components are started
-
Org. JBoss. seam. postauthenticate. <Name>-Called after User Authentication
-
Org. JBoss. seam. preauthenticate. <Name>-Called before trying to authenticate the user
-
Org. JBoss. seam. notloggedin-Called when user authentication is not required or authentication is required
-
Org. JBoss. seam. rememberme-This occurs when seam Security detects the user name in the cookie.
-
Org. JBoss. seam. exceptionhandled. <type>-Called when seam handles uncaptured exceptions
-
Org. JBoss. seam. exceptionhandled-Called when seam handles uncaptured exceptions
Org. JBoss. seam. exceptionnothandled-Called when no processor has caught exceptions
-
Org. JBoss. seam. aftertransactionsuccess-Called when the transaction is successful in seam Application Framework
-
Org. JBoss. seam. aftertransactionsuccess. <Name>-When the management is named<Name>Called when the entity transaction is successful in seam Application Framework
Seam components can observe any of these events in the same way they observe any other component-driven events.