在你编写一个Seam应用程序时,你会使用许多注释。Seam让你使用注释来实现声明模式编程。你使用的大多数注释由EJB3规范定义。数据校验注释由Hibernate Validator包定义。最后,Seam定义了它自己一组注释,我们将在本章描述它。
在org.jboss.seam.annotations包中定义了所有这些注释。
30.1. 用于组件定义的注释
第一组注释让我们定义Seam组件。这些注释出现在组件上。
@Name
@Name("componentName")
为类定义Seam组件名。所有Seam组件都需要这个注释。
@Scope
@Scope(ScopeType.CONVERSATION)
定义组件的默认上下文。ScopeType 枚举:EVENT, PAGE, CONVERSATION, SESSION, BUSINESS_PROCESS, APPLICATION, STATELESS 定义了可能的取值。
在没有明确指定作用域时,默认值取决于组件类型。对无状态会话beans,默认值为STATELESS。对实体beans 和有状态stateful会话beans,默认值为CONVERSATION。对于JavaBeans,默认值是EVENT。
@Role
@Role(name="roleName", scope=ScopeType.SESSION)
允许Seam组件绑定多个上下文变量。 @Name/@Scope注释定义了一个“默认角色”。每个@Role注释定义了一个附加角色。
· name — 上下文变量名。
· scope — 上下文变量的作用域。在没有明确指定作用域时,默认值取决于组件类型,如上面一样。
@Roles
@Roles({
@Role(name="user", scope=ScopeType.CONVERSATION),
@Role(name="currentUser", scope=ScopeType.SESSION)
})
允许指定多个附加角色。
@BypassInterceptors
@BypassInterceptors
在一个特殊的组件或一个组件的方法上禁用所有Seam拦截器。
@JndiName
@JndiName("my/jndi/name")
指定JNDI名, Seam使用它来查找EJB组件。如果没有明确指定JNDI名,Seam会使用JNDI 模式org.jboss.seam.core.init.jndiPattern指定。
@Conversational
@Conversational
指定对话作用域组件是对话式的,意味着只有一个长期运行对话是存活状态,组件的方法才可以被调用。
@PerNestedConversation
@PerNestedConversation
一个CONVERSATION-scoped组件的域仅局限于父对话,组件在此域被实例化。组件实例对嵌套子对话是不可见的,子对话会获得它们自己的实例。
警告:这是不明确的,因为它暗示一个组件对一个请求周期的某部分是可见的,而之后是不可见的。不推荐应用程序使用这个功能!
@Startup
@Scope(APPLICATION) @Startup(depends="org.jboss.seam.bpm.jbpm")
指定在初始化时立即启动application作用域组件。这主要应用于某些内建组件,引导关键的基础设施,如JNDI、数据源等等
@Scope(SESSION) @Startup
指定session作用域组件在会话创建时立即启动。
· depends —指定首先必须被启动的命名组件,如果它们已被安装。
@Install
@Install(false)
指定组件是否应该被默认安装。 缺少@Install注释,表明组件应该被安装。
@Install(dependencies="org.jboss.seam.bpm.jbpm")
指定组件仅在该组件列出的依赖组件被安装时才被安装。
@Install(genericDependencies=ManagedQueueSender.class)
指定组件仅在由某一个类实现的组件被安装时才被安装。这是有用的,在依赖组件没有一个专门的名字时。
@Install(classDependencies="org.hibernate.Session")
指定一个组件仅在命名类在类路径中时才被安装。
@Install(precedence=BUILT_IN)
指定组件的优先级。如果存在同名的多个组件,将安装优先级更高的组件。定义的优先级的值为 (用升序):
· BUILT_IN — 所有内建Seam组件优先
· FRAMEWORK —优先使用继承Seam 框架的组件
· APPLICATION —应用程序组件优先(默认优先级)
· DEPLOYMENT —优先使用在一个特定部署内覆盖应用程序组件的组件
· MOCK —用在测试中的模拟对象优先
@Synchronized
@Synchronized(timeout=1000)
指定多个客户端并发访问组件,并且Seam 应序列化请求。如果在给定的超时期间内,一个请求不能获得组件的锁,将抛出一个异常。
@ReadOnly
@ReadOnly
指定JavaBean组件或组件方法在调用结束时不必状态复制。
@AutoCreate
@AutoCreate
指定组件自动会被创建, 即使客户端没有指定create=true。
30.2. 用于双向注入的注释
下面两个注释控制双向注入。这些属性出现在组件实例变量或属性的accessor方法上。
@In
@In
指定在每个组件调用开始时,从一个上文变量注入组件属性。如果上下文变量为空,抛出一个异常。
@In(required=false)
指定在每个组件调用开始时,从一个上文变量注入组件属性。上下文变量可以为空。
@In(create=true)
指定在每个组件调用开始时,从一个上文变量注入组件属性。如果上下文变量为空,Seam实例化一个组件实例。
@In(value="contextVariableName")
明确指定上下文变量的名字,而不使用被注释的实例变量名字。
@In(value="#{customer.addresses['shipping']}")
指定在每个组件调用开始时,通过求JSF EL表达式的值注入组件属性。
· value — 指定上下文变量的名字。默认为组件属性名字。另外也可通过#{...}指定一个JSF EL表达式。
· create —如果在所有上下文中没有定义这个上下文变量,指定 Seam实例化组件时用同样的名字作为此上下文的变量名字。默认为false。
· required — 如果在所有上下文中没有定义这个上下文变量,指定Seam抛出一个异常。
@Out
@Out
指定在每个组件调用结束时,注出Seam组件属性到它的上下文变量中。如果属性为空,抛出一个异常。
@Out(required=false)
指定在每个组件调用结束时,注出Seam组件属性到它的上下文变量中。属性可以空。
@Out(scope=ScopeType.SESSION)
指定在调用结束时,注出一个非Seam组件的属性到一个特殊的作用域。
另外,如果没有明确指定scope,则使用@Out属性使用的组件作用域(如果组件是一个状态的,则使用EVENT作用域)。
@Out(value="contextVariableName")
明确指定上下文变量的名字,而不使用被注释的实例变量名字。
· value —指定上下文变量的名字。默认为组件属性的名字。
· required — 如果在注出期间,此组件的属性为空,指定Seam 应抛出一个异常。
注意,这些注释同时出现是相当普遍的,例如:
@In(create=true) @Out private User currentUser;
下面的注释支持manager component 模式,在该模式下,生命周期被一个Seam组件管理的某些其他类的实例会被注入。它出在组件的getter方法上。
@Unwrap
@Unwrap
指定由被注释的getter方法返回的对象是被注入的,而不是该组件实例自身。
下面的的注释支持factory component模式,在该模式下,一个Seam组件负责初始化上下文变量的值。这对初始化需要显示应答给non-faces请求的任何状态是尤其有用。它出现在一个组件方法上。
@Factory
@Factory("processInstance") public void createProcessInstance() { ... }
在上下文变量没有值时,指定组件方法初始化命名上下文变量的值。此方法返回void值 。
@Factory("processInstance", scope=CONVERSATION) public ProcessInstance createProcessInstance() { ... }
在上下文变量没有值时,指定方法返回一个值,Seam 应该用它来初始命名上下文变量的值。此方法返回一个值。如果没有明确指定scope ,组件的作用域和@Factory方法使用的一样(组件是无状态的,使用EVENT上下文)。
· value — 指定上下文变量的名字。如果方法是getter方法,默认为JavaBeans属性名。
· scope — 指定Seam应绑定返回值的作用域。只对返回一个值的工厂方法有意义。
· autoCreate — 指定无论是否变量被请求都自动调用这个工厂方法,即使@In没有指定create=true。
这个注释让你注入一个日志:
@Logger
@Logger("categoryName")
指定用org.jboss.seam.log.Log的一个实例注入一个组件字段。对实体beans,字段必须作为static被声明。
· value —指定日志分类的名字。默认为该组件类的名字。
最后一个注释让你注入一个请求参数:
@RequestParameter
@RequestParameter("parameterName")
指定使用一个请求参数的值注入一个组件的属性。基本类型转换被自动执行。
· value — 指定请求参数的名字。默认为该组件的属性名字。
30.3. 用于组件生命周期方法的注释
这些注释允许组件响应它自己的生命周期事件。它们出现在组件的方法上。每一个组件类只可能有一次。
@Create
@Create
指定在Seam实例化该组件的一个实例时要调用的方法。注意create方法只支持JavaBeans和有状态会话beans。
@Destroy
@Destroy
指定该上下文结束时和它的上下文变量销毁时要调用的方法。注意destroy方法只支持JavaBeans和有状态会话beans。
Destroy方法仅用于清除工作。Seam 捕获、记录、销毁destroy方法产生的的任何异常。
@Observer
@Observer("somethingChanged")
指定当一个指定类型的组件驱动(component-driven)事件发生时要调用的方法。
@Observer(value="somethingChanged",create=false)
指定当一个指定类型的事件发生时要调用的方法,但是如果实例不存在,也不会创建实例。如果一个实例不存在且create为false ,该事件不会被观察到。默认值为true.
30.4. 用于上下文划分的注释
这些注释提供声明式对话划分。它们出现在Seam组件的方法之上,通常在动作侦听器方法之上。
每个网页请求都有一个与它相联的对话上下文。大多数对话上下文在请求结束时也随之结束。如果你希望一个对话跨越多个请求,你必须通过调用被@Begin标记了的方法“提拔”当前的方法成为一个长期运行(long-running)对话。
@Begin
@Begin
指定当这个方法无异常地返回了一个非空结果时,长期运行对话开始。
@Begin(join=true)
指定如果一个长期运行对话是已在运行中,简单地拓展该对话上下文。
@Begin(nested=true)
指定如果一个长期运行对话是已在运行中,一个新的嵌套对话上下文开始。该嵌套对话在遭遇下一个@End时结束,并且外部对话会恢复。在同一个外部对话中同时存在多个嵌套对话,这是完全合法的。
@Begin(pageflow="process definition name")
指定一个jBPM 流程定义名,为这个对话定义页面流。
@Begin(flushMode=FlushModeType.MANUAL)
指定所有Seam 托管的持久化上下文的刷新模式。flushMode=FlushModeType.MANUAL 支持原子对话的使用,在这里所有的写操作在该对话上下文中被排队,直到明确地调用flush()才被执行(其通常发生在该对话结束时)。
· join —决定行为,当一个长期运行对话已在运行时。如果为true,拓展上下文。如果为false,抛出一个异常。默认为false。当指定nested=true,这个设置被忽略。
· nested —指定如果一个长期运行对话是已在运行中,一个新的嵌套对话上下文开始。
· flushMode — 设置在这个对话期间创建的所有Seam托管的Hibernate会话或JPA持久化上下文的刷新模式。
· pageflow —通过org.jboss.seam.bpm.jbpm.pageflowDefinitions部署的一个jBPM流程定义的一个流程定义名。
@End
@End
指定当这个方法无异常地返回了一个非空结果时,长期运行对话结束。
· beforeRedirect — 在默认时,实际上,直到所有重定向发生之后会话才被销毁。设置beforeRedirect=true,指定对话在当前请求结束时应被销毁,并且重定向将在一个新的临时对话上下文中被处理。
· root — 默认时,结束一个嵌套对话时简单地弹出会话堆栈,并恢复外部对话。设置root=true,指定根对话应被销毁,其有效地销毁了整个对话堆栈。如果对话没有嵌套,当前对话被简单地结束。
@StartTask
@StartTask
"启动"一个jBPM任务。指定当这个方法无异常地返回了一个非空结果时,开始一个长期运行对话。这个对话与用命名请求参数指定jBPM任务相关联。在这个对话上下文内,还为任务实例的业务流程实例定义了一个业务流程上下文。
· 通过一个名为taskInstance的请求上下文变量可使用jBPM TaskInstance 。 通过一个名为processInstance的请求上下文变量可使用jPBM ProcessInstance。(当然,这些对象也可通过@In注入后使用)
· taskIdParameter —用于保存任务id的请求参数名。默认为“taskId",它也是Seam taskList JSF组件的默认使用值 。
· flushMode —设置在这个对话期间创建的所有Seam托管的Hibernate会话或JPA持久化上下文的刷新模式。
@BeginTask
@BeginTask
恢复一个未完成的jBPM任务。指定当这个方法无异常地返回了一个非空结果时,开始一个长期运行对话。在这个对话上下文内,还为任务实例的业务流程实例定义了一个业务流程上下文。
· 通过一个名为taskInstance的请求上下文变量可使用jBPM org.jbpm.taskmgmt.exe.TaskInstance 。通过一个名为processInstance的请求上下文变量可使用jPBM org.jbpm.graph.exe.ProcessInstance 。
· taskIdParameter —用于保存任务id的请求参数名。默认为“taskId",它也是Seam taskList JSF组件的默认使用值 。
· flushMode —设置在这个对话期间创建的所有Seam托管的Hibernate会话或JPA持久化上下文的刷新模式。
@EndTask
@EndTask
"结束"一个jBPM任务。指定当这个方法无异常地返回了一个非空结果时,结束一个长期运行对话,并且完成当前任务。触发一个jBPM转换(transition)
。如果应用程序没有在名为transition
内建组件上调用Transition.setName(),触发的当前转换会被作为默认转换。
@EndTask(transition="transitionName")
触发给定的jBPM转换。
· transition — 在结束时,被触发的jBPM转换名字。
· beforeRedirect —在默认时,实际上,直到所有重定向发生之后会话才被销毁。设置beforeRedirect=true,指定对话在当前请求结束时应被销毁,并且重定向将在一个新的临时对话上下文中被处理。
@CreateProcess
@CreateProcess(definition="process definition name")
当方法无异常地返回了一个非空结果时,创建一个新的jBPM流程实例。通过一个名为processInstance的上下文变量可使用ProcessInstance对象。
· definition — 通过org.jboss.seam.bpm.jbpm.processDefinitions部署的jBPM流程定义名字。
@ResumeProcess
@ResumeProcess(processIdParameter="processId")
当方法无异常地返回了一个非空结果时,重新进入存在的jBPM 流程实例的作用域。通过一个名为processInstance 的上下文变量可使用ProcessInstance对象。
· processIdParameter — 保存流程id的一个请求参数名字。默认为“processeId”。
@Transition
@Transition("cancel")
只要方法返回一个非空结果,标记一个方法作为给当前jBPM流程实例发送一个转换的信号
。
30.5. 用于在J2EE 环境下使用Seam JavaBean 组件的注释
Seam提供了一个注释,让你对某些动作侦听结果强制进行JTA事务回滚。
@Transactional
@Transactional
指定一个JavaBean组件应该有与一个会话bean组件的默认行为类似的事务行为。即方法调用应该发生在一个事务内,并且如果在调用方法时没有事务存在,一个事务仅为该方法被启动。这个注释可以被用于类或方法层级。
不要在EJB 3.0组件上使用这个注释,使用@TransactionAttribute!
@ApplicationException
@ApplicationException
与使用在前面的Java EE 5环境的javax.ejb.ApplicationException同义。适用于一个异常来指示它是一个应用程序异常,并且应该被直接报告给客户端(即,展开)。
不要在EJB 3.0组件上使用这个注释,而应使用@javax.ejb.ApplicationException 。
· rollback — 默认为false, 如果为true ,这个异常将设置事务只回滚。
· end —默认为false, 如果为true ,这个异常将结束当前的长期运行对话。
·
@Interceptors
@Interceptors({DVDInterceptor, CDInterceptor})
与使用在前面的Java EE 5环境的javax.interceptors.Interceptors同义。注意它只能做为一个元注释使用。为一个类或方法声明一个拦截器有序列表
不要在EJB 3.0组件上使用这个注释,而应使用@javax.interceptor.Interceptors。
这些注释主要对JavaBean Seam组件有用。如果你使用EJB 3.0 组件,你应该使用标准的Java EE5 注释。
30.6. 用于异常的注释
这些注释让你指定Seam如何处理一个Seam组件产生的异常。
@Redirect
@Redirect(viewId="error.jsp")
指定被注释的异常导致一个浏览器重定向到一个指定的视图id。
· viewId — 指定重定向的JSF视图id 。在这里你可能使用EL。
· message — 被显示的消息, 默认为异常消息。
· end — 指定长期运行对话必须结束,默认为false。
@HttpError
@HttpError(errorCode=404)
指定被注释的异常导致一个HTTP错误被发送。
· errorCode —HTTP错误代码,默认为500。
· message —与HTTP错误一起发送的消息,默认为异常消息。
· end —指定长期运行对话必须结束,默认为false。
30.7. 用于Seam Remoting的注释
Seam Remoting 需要使用下面的注释来注释一个会话bean的本地接口:
@WebRemote
@WebRemote(exclude="path.to.exclude")
指明被注释的方法可以被客户边JavaScript调用。exclude属性是可选的,允许从结果对象图表中排除对象 (详细请看Remoting章)。
30.8. 用于Seam拦截器的注释
下面的注释出现在Seam拦截器的类上。
有关EJB拦截器定义需要的注释信息,请参考EJB 3.0规范文档。
@Interceptor
@Interceptor(stateless=true)
指定这个拦截器是无状态的,且可以优化复制。
@Interceptor(type=CLIENT)
指定这个拦截器是一个“客户边”拦截器,它在EJB容器之前被调用。
@Interceptor(around={SomeInterceptor.class, OtherInterceptor.class})
指定这个拦截器在堆栈中的位置比给定的拦截器更高。
@Interceptor(within={SomeInterceptor.class, OtherInterceptor.class})
指定这个拦截器在堆栈中的位置比给定的拦截器更深。
30.9. 用于异步的注释
下面的注释被用来声明一个异步方法,例如:
@Asynchronous public void scheduleAlert(Alert alert, @Expiration Date date) { ... }
@Asynchronous public Timer scheduleAlerts(Alert alert,
@Expiration Date date,
@IntervalDuration long interval) { ... }
@Asynchronous
@Asynchronous
指定方法调用被异步处理。
@Duration
@Duration
指定一个异步调用的参数,为此调用被处理之前的时间(或者首先处理重发的调用)。
@Expiration
@Expiration
指定一个异步调用的参数,为在此调用被处理时的时间(或者首先处理重发的调用)。
@IntervalDuration
@IntervalDuration
指定一个异步方法调用重发,这个注释参数为两个重发之间的时间。
30.10. 使用JSF的注释
下面的注释让操作JSF变得更容易。
@Converter
允许一个Seam组件作为一个JSF转换器。被注释的类必须是一个Seam组件,且必须实现javax.faces.convert.Converter接口。
· id —JSF转换器id。默认为组件名。
· forClass — 如果指定,注册这个组件作为一个类型的默认转换器。
@Validator
允许一个Seam组件作为一个JSF校验器。被注释的类必须是一个Seam组件,且必须实现javax.faces.validator.Validator接口。
· id —JSF校验器id。默认为组件名。
30.10.1. 使用dataTable的注释
下面的注释使一个有状态会话bean作为后台的可点击列表的实现变得容易。 它们出现在属性上。
@DataModel
@DataModel("variableName")
注出(Outjects)类型为List, Map, Set或Object[]的属性作为一个JSF DataModel到所属的组件作用域(或者EVENT作用域,如果所属组件是无状态的)。 在Map情况下,DataModel的每行是一个Map.Entry。
· value — 对话上下文变量名。默认为属性名。
· scope — 如果scope=ScopeType.PAGE被明确指定, DataModel 会被保持在PAGE上下文中。
@DataModelSelection
@DataModelSelection
从JSF DataModel注入所选的值 (其为底层集合的元素,或map的值). 如果只给一个组件定义了一个@DataModel属性,从这个DataModel所选的值会被注入。否则,必须在每个@DataModelSelection的值属性中指定每个@DataModel的组件名。