Weld SVN: r4361 - api/trunk/cdi/src/main/java/javax/enterprise/inject.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-10-28 18:34:41 -0400 (Wed, 28 Oct 2009)
New Revision: 4361
Modified:
api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
Log:
ws
Modified: api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-28 22:30:40 UTC (rev 4360)
+++ api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-28 22:34:41 UTC (rev 4361)
@@ -39,7 +39,7 @@
*
* <pre>
* public class BookShop
- extends Business
+ * extends Business
* implements Shop<Book> {
* ...
* }
15 years, 1 month
Weld SVN: r4360 - in api/trunk/cdi/src/main/java/javax: enterprise/inject and 1 other directory.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-10-28 18:30:40 -0400 (Wed, 28 Oct 2009)
New Revision: 4360
Modified:
api/trunk/cdi/src/main/java/javax/decorator/package-info.java
api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
Log:
lifecyle
Modified: api/trunk/cdi/src/main/java/javax/decorator/package-info.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/decorator/package-info.java 2009-10-28 18:05:04 UTC (rev 4359)
+++ api/trunk/cdi/src/main/java/javax/decorator/package-info.java 2009-10-28 22:30:40 UTC (rev 4360)
@@ -69,6 +69,10 @@
* final method, it may not have any decorator which implements
* that method.</p>
*
+ * <p>A decorator instance is a
+ * {@linkplain javax.enterprise.context.Dependent dependent object}
+ * of the object it decorates.</p>
+ *
* @see javax.enterprise.inject
*
* @see javax.decorator.Decorator
Modified: api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-28 18:05:04 UTC (rev 4359)
+++ api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-28 22:30:40 UTC (rev 4360)
@@ -400,6 +400,10 @@
* the bean.</li>
* </ul>
*
+ * <p>An interceptor instance is a
+ * {@linkplain javax.enterprise.context.Dependent dependent object}
+ * of the object it intercepts.</p>
+ *
* @see javax.enterprise.context
* @see javax.inject
* @see javax.interceptor
15 years, 1 month
Weld SVN: r4359 - api/trunk/cdi/src/main/java/javax/enterprise/inject.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-10-28 14:05:04 -0400 (Wed, 28 Oct 2009)
New Revision: 4359
Modified:
api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
Log:
minor
Modified: api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-28 18:00:04 UTC (rev 4358)
+++ api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-28 18:05:04 UTC (rev 4359)
@@ -314,22 +314,24 @@
*
* <p>Otherwise, the bean is said to be disabled.</p>
*
- * <h3>Dependency injection</h3>
+ * <h3>Inter-module injection</h3>
*
- * <p>A bean is eligible for injection into a given class if:</p>
+ * <p>A bean is available for injection in a certain Java EE module or library if:</p>
*
* <ul>
- * <li>The bean is enabled.</li>
- * <li>The bean is not an interceptor or decorator.</li>
- * <li>The bean is either not an alternative, or is a selected alternative of
- * the bean deployment archive of the given class.</li>
- * <li>In a Java EE or servlet container, the bean class is required to be
- * accessible to the given class, according to the class loading requirements
- * of the Java EE platform and Java Servlet specifications.</li>
+ * <li>the bean is enabled,</li>
+ * <li>the bean is either not an alternative, or the module or library is a bean
+ * deployment archive and the bean is a selected alternative of the bean deployment
+ * archive, and</li>
+ * <li>the bean class is required to be accessible to classes in the module or
+ * library, according to the class loading requirements of the Java EE platform and
+ * Java Servlet specifications.</li>
* </ul>
*
- * <p>A bean is eligible for injection into a given injection point if:</p>
+ * <h3>Dependency injection</h3>
*
+ * <p>A bean is assignable to a given injection point if:</p>
+ *
* <ul>
* <li>The bean has a bean type that matches the type of the injection point. For
* this purpose, primitive types are considered to match their corresponding wrapper
@@ -342,6 +344,14 @@
* point.</li>
* </ul>
*
+ * <p>A bean is eligible for injection into a given injection point if:</p>
+ *
+ * <ul>
+ * <li>it is available for injection in the Java EE module or library that contains
+ * the class that declares the injection point, and</li>
+ * <li>it is assignable to the injection point.</li>
+ * </ul>
+ *
* <p>If more than one bean is eligible for injection to the injection point, the
* container attempts to resolve the ambiguity by eliminating all beans which are
* not alternatives.</p>
@@ -366,12 +376,8 @@
*
* <ul>
* <li>The bean has the given EL name.</li>
- * <li>The bean is enabled.</li>
- * <li>The bean is either not an alternative, or is a selected alternative of the
- * war containing the JSP or JSF page with the EL expression.</li>
- * <li>The bean class is required to be accessible to classes in the war containing
- * the JSP or JSF page with the EL expression, according to the class loading
- * requirements of the Java EE platform and Java Servlet specifications.</li>
+ * <li>the bean is available for injection in the war containing the JSP or JSF
+ * page with the EL expression.</li>
* </ul>
*
* <p>If an EL name resolves to more than one bean, the container attempts to resolve
15 years, 1 month
Weld SVN: r4358 - api/trunk/cdi/src/main/java/javax/enterprise/inject/spi.
by weld-commits@lists.jboss.org
Author: dallen6
Date: 2009-10-28 14:00:04 -0400 (Wed, 28 Oct 2009)
New Revision: 4358
Modified:
api/trunk/cdi/src/main/java/javax/enterprise/inject/spi/BeanManager.java
Log:
Updated JavaDocs on BeanManager interface
Modified: api/trunk/cdi/src/main/java/javax/enterprise/inject/spi/BeanManager.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/enterprise/inject/spi/BeanManager.java 2009-10-28 17:56:15 UTC (rev 4357)
+++ api/trunk/cdi/src/main/java/javax/enterprise/inject/spi/BeanManager.java 2009-10-28 18:00:04 UTC (rev 4358)
@@ -32,15 +32,40 @@
import javax.enterprise.inject.UnsatisfiedResolutionException;
/**
- * The contract between the application and the manager. Also the contract
- * between the manager and Bean, Context and Observer objects.
+ * <p>
+ * This interface provides operations for obtaining contextual references for
+ * beans, along with many other operations of use to portable extensions.
+ * Occasionally it is necessary to use this programmatic API to fully utilize
+ * portable extensions in the Contexts and Dependency Injection for the Java EE
+ * platform standard.
+ * </p>
+ * <p>
+ * The container provides a built-in bean with bean type BeanManager, scope
+ * {@literal @}{@link javax.enterprise.context.Dependent} and qualifier
+ * {@literal @}{@link javax.enterprise.inject.Default}. The built-in
+ * implementation is a {@linkplain PassivationCapable passivation capable}
+ * dependency. Thus, any bean may obtain an instance of BeanManager by injecting
+ * it:
+ * </p>
*
- * The application should not normally need to call this interface.
+ * <pre>
+ * @Inject
+ * BeanManager manager;
+ * </pre>
+ * <p>
+ * Java EE components may also obtain an instance of BeanManager from
+ * {@linkplain javax.naming JNDI} by looking up the name {@code
+ * java:comp/BeanManager}.
+ * </p>
+ * <p>
+ * Any operation of BeanManager may be called at any time during the execution
+ * of the application.
+ * </p>
*
* @author Gavin King
* @author Pete Muir
* @author Clint Popetz
- *
+ * @author David Allen
*/
public interface BeanManager
{
@@ -48,7 +73,7 @@
/**
* Obtains a contextual reference for a given bean and a given bean type.
*
- * @param bean the Bean object representing the bean
+ * @param bean the {@link Bean} object representing the bean
* @param beanType a bean type that must be implemented by any proxy that is
* returned
* @return a contextual reference representing the bean
@@ -58,10 +83,9 @@
public Object getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx);
/**
- * Obtains an instance of bean for a given injection point.
+ * Obtains an instance of bean for a given injection point. This method
+ * should not be called by an application.
*
- * This method should not be called by an application.
- *
* @param ij the injection point the instance is needed for
* @param ctx the context in which the injection is occurring
* @return an instance of the bean
@@ -81,12 +105,11 @@
public <T> CreationalContext<T> createCreationalContext(Contextual<T> contextual);
/**
- * Returns the set of beans which match the given required type and qualifiers
- * and are accessible to the class into which the BeanManager was injected,
- * according to the rules of typesafe resolution.
+ * Returns the set of beans which match the given required type and
+ * qualifiers and are accessible to the class into which the BeanManager was
+ * injected, according to the rules of typesafe resolution. Typesafe
+ * resolution usually occurs at container deployment time.
*
- * Typesafe resolution usually occurs at container deployment time.
- *
* @param beanType the type of the beans to be resolved
* @param qualifiers the qualifiers used to restrict the matched beans. If no
* qualifiers are passed to getBeans(), the default binding @Current
@@ -112,11 +135,13 @@
public Set<Bean<?>> getBeans(String name);
/**
- * Returns the Bean object representing the most specialized enabled bean
- * registered with the container that specializes the given bean,
+ * Returns the {@link Bean} object representing the
+ * most specialized enabled bean registered with the container that
+ * specializes the given bean,
*
- * @param <X> The type of the bean
- * @param bean The Bean representation of the bean.
+ * @param <X> the type of the bean
+ * @param bean the {@link Bean} representation of the
+ * bean.
* @return the most specialized enabled bean
*/
public <X> Bean<? extends X> getMostSpecializedBean(Bean<X> bean);
@@ -129,15 +154,15 @@
/**
* Apply the ambiguous dependency resolution rules
*
- * @param <X> The type of the bean
- * @param beans A set of beans of the given type
+ * @param <X> the type of the bean
+ * @param beans a set of beans of the given type
* @throws AmbiguousResolutionException if the ambiguous dependency
* resolution rules fail
*/
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans);
/**
- * Validates the dependency
+ * Validates the injection point dependency.
*
* @param injectionPoint the injection point to validate
* @throws an InjectionException if there is a deployment problem (for
@@ -147,10 +172,11 @@
public void validate(InjectionPoint injectionPoint);
/**
- * Fire an event
+ * Fires an event and notifies observers.
*
* @param event the event object
- * @param qualifiers the event qualifiers used to restrict the observers matched
+ * @param qualifiers the event qualifiers used to restrict the observers
+ * matched
* @throws IllegalArgumentException if the runtime type of the event object
* contains a type variable
* @throws IllegalArgumentException if two instances of the same binding type
@@ -178,7 +204,7 @@
/**
* Obtains an ordered list of enabled decorators for a set of bean types and
- * a set of qualifiers
+ * a set of qualifiers.
*
* @param types the set of bean types of the decorated bean
* @param qualifiers the qualifiers declared by the decorated bean
@@ -192,11 +218,12 @@
public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers);
/**
- * Obtains an ordered list of enabled interceptors for a set interceptor
- * bindings
+ * Obtains an ordered list of enabled interceptors for a set of interceptor
+ * bindings.
*
* @param type the type of the interception
- * @param interceptorBindings the bindings used to restrict the matched interceptors
+ * @param interceptorBindings the bindings used to restrict the matched
+ * interceptors
* @return the resolved interceptors
* @throws IllegalArgumentException if no interceptor binding type is passed
* @throws IllegalArgumentException if an annotation which is not a
@@ -207,100 +234,153 @@
public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings);
/**
- * Determine if the given annotationType is a scope type
+ * Tests the given annotationType to determine if it is a
+ * {@linkplain javax.enterprise.context scope type}.
+ *
+ * @param annotationType the annotation to test
+ * @return true if the annotation is a {@linkplain javax.enterprise.context
+ * scope type}
*/
public boolean isScope(Class<? extends Annotation> annotationType);
-
+
+ /**
+ * Tests the given annotationType to determine if it is a normal
+ * {@linkplain javax.enterprise.context scope type}.
+ *
+ * @param annotationType the annotation to test
+ * @return true if the annotation is a normal
+ * {@linkplain javax.enterprise.context scope type}
+ */
public boolean isNormalScope(Class<? extends Annotation> annotationType);
-
+
+ /**
+ * Tests the given annotationType to determine if it is a passivating
+ * {@linkplain javax.enterprise.context scope type}.
+ *
+ * @param annotationType the annotation to test
+ * @return true if the annotation is a passivating
+ * {@linkplain javax.enterprise.context scope type}
+ */
public boolean isPassivatingScope(Class<? extends Annotation> annotationType);
/**
- * Determine if the given annotationType is a binding type
+ * Tests the given annotationType to determine if it is a
+ * {@linkplain javax.inject.Qualifier qualifier type}.
+ *
+ * @param annotationType the annotation to test
+ * @return true if the annotation is a {@linkplain javax.inject.Qualifier
+ * qualifier type}
*/
public boolean isQualifier(Class<? extends Annotation> annotationType);
/**
- * Determine if the given annotationType is an interceptor binding type
+ * Tests the given annotationType to determine if it is an
+ * {@linkplain Interceptor interceptor} binding type.
+ *
+ * @param annotationType the annotation to test
+ * @return true if the annotationType is a {@linkplain Interceptor
+ * interceptor} binding type
*/
public boolean isInterceptorBindingType(Class<? extends Annotation> annotationType);
/**
- * Determine if the given annotationType is a stereotype
+ * Tests the given annotationType to determine if it is a
+ * {@linkplain javax.enterprise.inject.Stereotype stereotype}.
+ *
+ * @param annotationType the annotation to test
+ * @return true if the annotationType is a
+ * {@linkplain javax.enterprise.inject.Stereotype stereotype}
*/
public boolean isStereotype(Class<? extends Annotation> annotationType);
/**
- * Obtain the set of interceptor binding types meta-annotatinos for the given
- * binding type annotation
+ * Obtains the set of meta-annotations for an {@linkplain Interceptor
+ * interceptor} binding type.
+ *
+ * @param bindingType the annotation for which to obtain meta-annotations
+ * @return the set of meta-annotations for the given {@linkplain Interceptor
+ * interceptor} binding type
*/
public Set<Annotation> getInterceptorBindingTypeDefinition(Class<? extends Annotation> bindingType);
/**
- * Obtain the set of binding types meta-annotations for the given stereotype
- * annotation
+ * Obtains meta-annotations for a
+ * {@linkplain javax.enterprise.inject.Stereotype stereotype}.
+ *
+ * @param stereotype the {@linkplain javax.enterprise.inject.Stereotype
+ * stereotype} for which to obtain meta-annotations
+ * @return the set of meta-annotations for the given
+ * {@linkplain javax.enterprise.inject.Stereotype stereotype}
*/
public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype);
-
+
/**
- * Obtain an active context instance for the given scope type.
+ * Obtains an active {@linkplain javax.enterprise.context.spi.Context
+ * context} instance for the given {@linkplain javax.enterprise.context scope
+ * type}.
*
- * @param scopeType the scope to get the context instance for
- * @return the context instance
+ * @param scopeType the {@linkplain javax.enterprise.context scope} to get
+ * the context instance for
+ * @return the {@linkplain javax.enterprise.context.spi.Context context}
+ * instance
* @throws ContextNotActiveException if no active contexts exist for the
* given scope type
* @throws IllegalArgumentException if more than one active context exists
* for the given scope type
*/
public Context getContext(Class<? extends Annotation> scopeType);
-
+
/**
- * Returns the ELResolver for integration with the servlet engine and JSF
- * implementation This resolver will return a contextual instance of a bean
- * if the name for resolution resolves to exactly one bean
+ * Returns the {@link javax.el.ELResolver} for integration with the servlet
+ * engine and JSF implementation. This resolver will return a contextual
+ * instance of a bean if the name for resolution resolves to exactly one
+ * bean.
*/
public ELResolver getELResolver();
-
+
/**
- * Returns an ExpressionFactory
+ * Returns a wrapper {@link javax.el.ExpressionFactory} that delegates
+ * {@link javax.el.MethodExpression} and {@link javax.el.ValueExpression}
+ * creation to the given {@link javax.el.ExpressionFactory}. When a Unified
+ * EL expression is evaluated using a {@link javax.el.MethodExpression} or
+ * {@link javax.el.ValueExpression} returned by the wrapper
+ * {@link javax.el.ExpressionFactory}
*
- * @param expressionFactory
- * @return
+ * @param expressionFactory the expression factory to wrap
+ * @return the wrapped {@link javax.el.ExpressionFactory}
*/
public ExpressionFactory wrapExpressionFactory(ExpressionFactory expressionFactory);
-
+
/**
* Get an {@link AnnotatedType} for the given class
+ *
* @param <T> the type
* @param type the type
* @return the {@link AnnotatedType}
*/
public <T> AnnotatedType<T> createAnnotatedType(Class<T> type);
-
+
/**
* Returns an InjectionTarget to allow injection into custom beans or
- * non-contextual instances by portable extensions.
+ * non-contextual instances by portable extensions. The container ignores the
+ * annotations and types declared by the elements of the actual Java class
+ * and uses the metadata provided via the Annotated interface instead.
*
- * The container ignores the annotations and types declared by the elements
- * of the actual Java class and uses the metadata provided via the Annotated
- * interface instead.
- *
- * @param <T> The type of the AnnotatedType to inspect
- * @param type The AnnotatedType to inspect
+ * @param <T> the type of the AnnotatedType to inspect
+ * @param type the AnnotatedType to inspect
* @returns a container provided instance of InjectionTarget for the given
* type
* @throws IllegalArgumentException if there is a definition error associated
* with any injection point of the type.
*/
public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type);
-
+
/**
* Allows a new bean to be registered. This fires a ProcessBean event and
* then registers a new bean with the container, thereby making it available
- * for injection into other beans.
+ * for injection into other beans. This method may be called at any time in
+ * the applications lifecycle.
*
- * This method may be called at any time in the applications lifecycle.
- *
* @param bean the bean to register
*/
@Deprecated
15 years, 1 month
Weld SVN: r4357 - build/trunk/dist.
by weld-commits@lists.jboss.org
Author: dan.j.allen
Date: 2009-10-28 13:56:15 -0400 (Wed, 28 Oct 2009)
New Revision: 4357
Modified:
build/trunk/dist/readme.txt
Log:
don't mention Weld version number
mention Java EE 5 retrofitted
mention support for Apache Tomcat 6 and Jetty 6 in marked examples
Modified: build/trunk/dist/readme.txt
===================================================================
--- build/trunk/dist/readme.txt 2009-10-28 16:42:55 UTC (rev 4356)
+++ build/trunk/dist/readme.txt 2009-10-28 17:56:15 UTC (rev 4357)
@@ -16,12 +16,17 @@
System requirements
===================
- Weld 1.0 requires a Java EE 6 application server, a servlet container (using
- the servlet extension) and Java SE (using the Java SE extension).
+ Weld examples require either a Java EE 6 application server, a Java EE 5
+ application server retrofitted to include CDI support, a servlet container
+ (using the Weld servlet extension) and Java SE (using the Weld Java SE
+ extension). In fact, through extensions, Weld can accomodate any Java
+ environment.
- You must use JBoss AS 5.2.0.Beta1 (use nightly builds until released) or above
- to deploy the provided examples out of the box. Other application servers may
- be supported by the examples in the 1.0.0 release.
+ Currently, you must use JBoss AS 5.2.0.Beta1 (use nightly builds until
+ released) or above deploy the provided examples out of the box. Marked
+ examples, which do not include EJB session beans, can also be deployed to
+ Apache Tomcat 6 or Jetty 6. Other application servers may be supported by
+ the examples in the 1.0.0 release.
JDK 5.0 or JDK 6.0 is required for all Weld releases.
15 years, 1 month
Weld SVN: r4356 - core/trunk/impl/src/main/java/org/jboss/weld/servlet.
by weld-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2009-10-28 12:42:55 -0400 (Wed, 28 Oct 2009)
New Revision: 4356
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletHelper.java
Log:
Better error messages
Modified: core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletHelper.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletHelper.java 2009-10-27 18:59:53 UTC (rev 4355)
+++ core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletHelper.java 2009-10-28 16:42:55 UTC (rev 4356)
@@ -34,10 +34,16 @@
{
if (ctx == null)
{
- throw new IllegalArgumentException("Must provide the Servlet Context");
+ throw new IllegalArgumentException("ServletContext is null");
}
BeanDeploymentArchive beanDeploymentArchive = Container.instance().deploymentServices().get(ServletServices.class).getBeanDeploymentArchive(ctx);
- return Container.instance().beanDeploymentArchives().get(beanDeploymentArchive).getCurrent();
+ BeanManagerImpl beanManagerImpl = Container.instance().beanDeploymentArchives().get(beanDeploymentArchive);
+ if (beanManagerImpl == null)
+ {
+ throw new IllegalArgumentException("Unable to find BeanManager. BeanDeploymentArchive: " + beanDeploymentArchive + "; ServletContext: " + ctx);
+ }
+ // Actually we need the manager for the current activity
+ return beanManagerImpl.getCurrent();
}
}
15 years, 1 month
Weld SVN: r4355 - api/trunk/cdi/src/main/java/javax/enterprise/inject.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-10-27 14:59:53 -0400 (Tue, 27 Oct 2009)
New Revision: 4355
Modified:
api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
Log:
interceptor restrictions
Modified: api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-27 18:59:13 UTC (rev 4354)
+++ api/trunk/cdi/src/main/java/javax/enterprise/inject/package-info.java 2009-10-27 18:59:53 UTC (rev 4355)
@@ -179,6 +179,11 @@
* }
* </pre>
*
+ * <p>If a managed bean class is declared final, it may not have any interceptor
+ * bindings. If a managed bean has a non-static, non-private, final method, it
+ * may not have any class-level interceptor bindings, and that method may not
+ * have any method-level interceptor bindings.</p>
+ *
* <h3>Bean implementation</h3>
*
* <p>The container provides built-in support for injection and contextual
15 years, 1 month
Weld SVN: r4354 - api/trunk/cdi/src/main/java/javax/decorator.
by weld-commits@lists.jboss.org
Author: gavin.king(a)jboss.com
Date: 2009-10-27 14:59:13 -0400 (Tue, 27 Oct 2009)
New Revision: 4354
Modified:
api/trunk/cdi/src/main/java/javax/decorator/package-info.java
Log:
decorator restriction
Modified: api/trunk/cdi/src/main/java/javax/decorator/package-info.java
===================================================================
--- api/trunk/cdi/src/main/java/javax/decorator/package-info.java 2009-10-27 18:51:33 UTC (rev 4353)
+++ api/trunk/cdi/src/main/java/javax/decorator/package-info.java 2009-10-27 18:59:13 UTC (rev 4354)
@@ -19,11 +19,11 @@
*
* <h3>Decorated types</h3>
*
- * <p>The set of decorated types
- * of a decorator includes all interfaces implemented directly or
- * indirectly by the bean class, except for {@link java.io.Serializable}.
- * The decorator bean class and its superclasses are not decorated
- * types of the decorator. The decorator class may be abstract.</p>
+ * <p>The set of decorated types of a decorator includes all
+ * interfaces implemented directly or indirectly by the bean class,
+ * except for {@link java.io.Serializable}. The decorator bean
+ * class and its superclasses are not decorated types of the
+ * decorator. The decorator class may be abstract.</p>
*
* <p>A decorator intercepts every method:</p>
* <ul>
@@ -64,6 +64,11 @@
* the bean.</li>
* </ul>
*
+ * <p>If a managed bean class is declared final, it may not have
+ * decorators. If a managed bean has a non-static, non-private,
+ * final method, it may not have any decorator which implements
+ * that method.</p>
+ *
* @see javax.enterprise.inject
*
* @see javax.decorator.Decorator
15 years, 1 month
Weld SVN: r4353 - in examples/trunk/jsf: permalink and 18 other directories.
by weld-commits@lists.jboss.org
Author: dan.j.allen
Date: 2009-10-27 14:51:33 -0400 (Tue, 27 Oct 2009)
New Revision: 4353
Added:
examples/trunk/jsf/permalink/
examples/trunk/jsf/permalink/pom.xml
examples/trunk/jsf/permalink/readme.txt
examples/trunk/jsf/permalink/src/
examples/trunk/jsf/permalink/src/main/
examples/trunk/jsf/permalink/src/main/java/
examples/trunk/jsf/permalink/src/main/java/org/
examples/trunk/jsf/permalink/src/main/java/org/jboss/
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Blog.java
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntry.java
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntryRepository.java
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Comment.java
examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/CommentBoard.java
examples/trunk/jsf/permalink/src/main/resources/
examples/trunk/jsf/permalink/src/main/resources/META-INF/
examples/trunk/jsf/permalink/src/main/resources/META-INF/beans.xml
examples/trunk/jsf/permalink/src/main/resources/log4j.xml
examples/trunk/jsf/permalink/src/main/webapp/
examples/trunk/jsf/permalink/src/main/webapp/META-INF/
examples/trunk/jsf/permalink/src/main/webapp/META-INF/context.xml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/faces-config.xml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/categories.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/comments.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/commonViewParams.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryContent.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryList.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/otherCategories.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/singleEntry.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/jetty-env.xml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/layout/
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/layout/template.xhtml
examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/web.xml
examples/trunk/jsf/permalink/src/main/webapp/category.xhtml
examples/trunk/jsf/permalink/src/main/webapp/css/
examples/trunk/jsf/permalink/src/main/webapp/css/legacy.css
examples/trunk/jsf/permalink/src/main/webapp/css/style.css
examples/trunk/jsf/permalink/src/main/webapp/entry.xhtml
examples/trunk/jsf/permalink/src/main/webapp/favicon.ico
examples/trunk/jsf/permalink/src/main/webapp/home.xhtml
examples/trunk/jsf/permalink/src/main/webapp/img/
examples/trunk/jsf/permalink/src/main/webapp/img/bodybg.gif
examples/trunk/jsf/permalink/src/main/webapp/img/headerbg.gif
examples/trunk/jsf/permalink/src/main/webapp/img/rss.gif
examples/trunk/jsf/permalink/src/main/webapp/img/search.png
examples/trunk/jsf/permalink/src/main/webapp/img/searchbg.gif
examples/trunk/jsf/permalink/src/main/webapp/img/technorati.gif
examples/trunk/jsf/permalink/src/main/webapp/img/wgradient.png
examples/trunk/jsf/permalink/src/main/webapp/img/wrapper.gif
examples/trunk/jsf/permalink/src/main/webapp/index.html
examples/trunk/jsf/permalink/src/test/
examples/trunk/jsf/permalink/src/test/java/
examples/trunk/jsf/permalink/src/test/resources/
Log:
add permalink example
Property changes on: examples/trunk/jsf/permalink
___________________________________________________________________
Name: svn:ignore
+ .classpath
.project
.settings
target
Added: examples/trunk/jsf/permalink/pom.xml
===================================================================
--- examples/trunk/jsf/permalink/pom.xml (rev 0)
+++ examples/trunk/jsf/permalink/pom.xml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.jboss.weld.examples</groupId>
+ <artifactId>weld-examples-parent</artifactId>
+ <version>1.0.0-CR1</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.jboss.weld.examples.jsf</groupId>
+ <artifactId>weld-jsf-permalink</artifactId>
+ <packaging>war</packaging>
+ <name>Weld Permalink Example (Servlet)</name>
+ <description>The Weld permalink example for deployment to a servlet environment</description>
+
+ <properties>
+ <jetty.http.port>9090</jetty.http.port>
+ <jetty.stop.port>9091</jetty.stop.port>
+ <jetty.debug.port>9190</jetty.debug.port>
+ <jetty.daemon>false</jetty.daemon>
+ <tomcat.http.port>8080</tomcat.http.port>
+ <embedded-tomcat.http.port>9090</embedded-tomcat.http.port>
+ <embedded-tomcat.debug.port>9190</embedded-tomcat.debug.port>
+ <webapp.directory>src/main/webapp</webapp.directory>
+ </properties>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>codehaus repository</id>
+ <url>http://repository.codehaus.org/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ <classifier>jdk15</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.faces</groupId>
+ <artifactId>jsf-impl</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <!-- needed for reference by maven-eclipse-plugin -->
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>jta</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <version>4.0.0.GA</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.5.6</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.weld.servlet</groupId>
+ <artifactId>weld-servlet</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.web</groupId>
+ <artifactId>el-impl</artifactId>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.el</groupId>
+ <artifactId>el-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <defaultGoal>package</defaultGoal>
+ <!--
+ <finalName>${project.artifactId}</finalName>
+ -->
+ <finalName>weld-permalink</finalName>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <failOnError>false</failOnError>
+ <filesets>
+ <fileset>
+ <!-- clean up files from war:inplace -->
+ <directory>${webapp.directory}</directory>
+ <includes>
+ <include>WEB-INF/classes/**</include>
+ <include>WEB-INF/lib/**</include>
+ </includes>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <additionalBuildcommands>
+ <!-- annoyingly creates a bin directory
+ <buildCommand>
+ <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+ </buildCommand>
+ -->
+ <buildCommand>
+ <name>org.jboss.tools.common.verification.verifybuilder</name>
+ </buildCommand>
+ </additionalBuildcommands>
+ <additionalConfig>
+ <file>
+ <name>.settings/org.maven.ide.eclipse.prefs</name>
+ <content>activeProfiles=jdk5
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1</content>
+ </file>
+ </additionalConfig>
+ <additionalProjectFacets>
+ <jst.jsf>1.2</jst.jsf> <!-- 2.0 is not yet supported -->
+ </additionalProjectFacets>
+ <additionalProjectnatures>
+ <projectnature>org.eclipse.wst.jsdt.core.jsNature</projectnature>
+ <projectnature>org.jboss.tools.jsf.jsfnature</projectnature>
+ </additionalProjectnatures>
+ <workspace>${user.home}/.eclipse/workspace</workspace>
+ <wtpdefaultserver>JBoss</wtpdefaultserver>
+ <wtpversion>1.5</wtpversion>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <!-- don't stage or package files added to ${webapp.directory} by war:inplace -->
+ <warSourceExcludes>WEB-INF/classes/**,WEB-INF/lib/**</warSourceExcludes>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>tomcat-maven-plugin</artifactId>
+ <configuration>
+ <path>/${project.build.finalName}</path>
+ <!-- uncomment to use server configuration override; see readme.txt for details -->
+ <!--<server>tomcatserver</server>-->
+ <url>http://localhost:${tomcat.http.port}/manager</url>
+ <port>${embedded-tomcat.http.port}</port> <!-- port for embedded Tomcat only (putting this configuration in the execution for the run goal doesn't work) -->
+ <!-- if you don't want to use war:inplace, uncomment this setting -->
+ <!--
+ <warSourceDirectory>${project.build.directory}/${project.build.finalName}</warSourceDirectory>
+ -->
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>maven-jetty-plugin</artifactId>
+ <configuration>
+ <connectors>
+ <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
+ <port>${jetty.http.port}</port>
+ <maxIdleTime>3600000</maxIdleTime>
+ </connector>
+ </connectors>
+ <daemon>${jetty.daemon}</daemon>
+ <stopPort>${jetty.stop.port}</stopPort>
+ <stopKey>HASTA_LA_VISTA</stopKey>
+ <scanIntervalSeconds>10</scanIntervalSeconds>
+ <webAppConfig>
+ <contextPath>/${project.build.finalName}</contextPath>
+ </webAppConfig>
+ <!-- if you don't want to use war:inplace, uncomment this setting -->
+ <!--
+ <webAppSourceDirectory>${project.build.directory}/${project.build.finalName}</webAppSourceDirectory>
+ -->
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.twdata.maven</groupId>
+ <artifactId>maven-cli-plugin</artifactId>
+ <version>0.6.3.CR3</version>
+ <configuration>
+ <prompt>${project.artifactId}</prompt>
+ <!-- userAliases are for cli:execute-phase -->
+ <userAliases>
+ <runjetty>compile org.apache.maven.plugins:maven-war-plugin:inplace org.mortbay.jetty:maven-jetty-plugin:run</runjetty>
+ <stopjetty>org.mortbay.jetty:maven-jetty-plugin:stop</stopjetty>
+ <runtomcat>compile org.apache.maven.plugins:maven-war-plugin:inplace org.codehaus.mojo:tomcat-maven-plugin:run</runtomcat>
+ <explode>compile org.apache.maven.plugins:maven-war-plugin:inplace -o</explode>
+ <restart>org.apache.maven.plugins:maven-antrun-plugin:run -Prestart-embedded</restart>
+ <!--<restart>validate -Prestart-embedded -o</restart>-->
+ <profiles>org.apache.maven.plugins:maven-help-plugin:active-profiles -o</profiles>
+ <pom>org.apache.maven.plugins:maven-help-plugin:effective-pom -o</pom>
+ </userAliases>
+ <!-- commands are for cli:execute -->
+ <commands>
+ </commands>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>restart-embedded</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <configuration>
+ <tasks>
+ <touch file="${webapp.directory}/WEB-INF/web.xml"/>
+ </tasks>
+ </configuration>
+ <!-- Hooking an execution to a phase is more correct, but slower -->
+ <!--
+ <executions>
+ <execution>
+ <id>touch-web-inf</id>
+ <phase>validate</phase>
+ <configuration>
+ <tasks>
+ <touch file="${webapp.directory}/WEB-INF/web.xml"/>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ -->
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
Added: examples/trunk/jsf/permalink/readme.txt
===================================================================
--- examples/trunk/jsf/permalink/readme.txt (rev 0)
+++ examples/trunk/jsf/permalink/readme.txt 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,98 @@
+Weld Permalink Example (Servlet Environment)
+============================================
+
+This example demonstrates the use of Weld in a Servlet environment (Tomcat 6
+/ Jetty 6). Contextual state management and dependency injection are handled by
+JSR-299. Transaction and persistence context management is handled by the EJB 3
+container. No alterations are required to be made to the Servlet container. All
+services are self-contained within the deployment.
+
+This example uses a Maven 2 build. Execute the following command to build the
+WAR. The WAR will will be located in the target directory after completion of
+the build.
+
+ mvn
+
+Now you are ready to deploy.
+
+== Deploying with an embedded servlet container
+
+Run this command to execute the application in an embedded Jetty 6 container:
+
+ mvn war:inplace jetty:run
+
+You can also execute the application in an embedded Tomcat 6 container:
+
+ mvn war:inplace tomcat:run
+
+In both cases, any changes to assets in src/main/webapp take affect
+immediately. If a change to a webapp configuration file is made, the
+application may automatically redeploy. The redeploy behavior can be fined
+tuned in the plugin configuration (at least for Jetty). If you make a change
+to a classpath resource, you need to execute a build:
+
+ mvn compile war:inplace
+
+Note that war:inplace copies the compiled classes and JARs inside WebContent,
+under WEB-INF/classes and WEB-INF/lib, respectively, mixing source and compiled
+files. However, the build does work around these temporary files by excluding
+them from the packaged WAR and cleaning them during the Maven clean phase.
+These folders are also ignored by SVN.
+
+== Deploying to standalone Tomcat
+
+If you want to run the application on a standalone Tomcat 6, first download and
+extract Tomcat 6. This build assumes you will be running Tomcat in its default
+configuration, with a hostname of localhost and port 8080. Before starting
+Tomcat, add the following line to conf/tomcat-users.xml to allow the Maven
+Tomcat plugin to access the manager application, then start Tomcat:
+
+ <user username="admin" password="" roles="manager"/>
+
+To override this username and password, add a <server> with id tomcat in your
+Maven 2 settings.xml file, set the <username> and <password> elements to the
+appropriate values and uncomment the <server> element inside the
+tomcat-maven-plugin configuration in the pom.xml.
+
+You can deploy the packaged archive to Tomcat via HTTP PUT using this command:
+
+ mvn package tomcat:deploy
+
+Then you use this command to undeploy the application:
+
+ mvn tomcat:undeploy
+
+Instead of packaging the WAR, you can deploy it as an exploded archive
+immediately after the war goal is finished assembling the exploded structure:
+
+ mvn compile war:exploded tomcat:exploded
+
+Once the application is deployed, you can redeploy it using the following command:
+
+ mvn tomcat:redeploy
+
+But likely you want to run one or more build goals first before you redeploy:
+
+ mvn compile tomcat:redeploy
+ mvn war:exploded tomcat:redeploy
+ mvn compile war:exploded tomcat:redeploy
+
+= Importing the project into Eclipse
+
+The recommended way to setup a Seam example in Eclipse is to use the m2eclipse
+plugin. This plugin derives the build classpath from the dependencies listed in
+the pom.xml file. It also has direct integration with Maven build commands.
+
+To get started open Eclipse and import the project by selecting "Maven
+Projects" and browsing to the project folder. You can now develop the project
+in Eclipse just like any other project.
+
+You could also prepare the Eclipse project before hand, then import the project
+into Eclipse. First, transform the pom.xml into an m2eclipse Eclipse project
+using this command:
+
+ mvn eclipse:m2eclipse
+
+Now go into Eclipse an import the project by selecting "Existing projects into
+workspace" and selecting the project folder. Both approaches use the Eclipse
+project configuration defined in the pom.xml file.
Added: examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Blog.java
===================================================================
--- examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Blog.java (rev 0)
+++ examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Blog.java 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,322 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.weld.examples.permalink;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * @author Dan Allen
+ */
+public
+@Named
+@RequestScoped
+class Blog
+{
+ private static final int PAGE_SIZE = 3;
+
+ @Inject BlogEntryRepository repository;
+
+ private Long entryId;
+
+ private String category;
+
+ private BlogEntry entry;
+
+ private List<BlogEntry> entriesForPage;
+
+ private List<String> categories;
+
+ private boolean nextPageAvailable;
+
+ private int page = 1;
+
+ private String searchString;
+
+ public Long getEntryId()
+ {
+ return entryId;
+ }
+
+ public void setEntryId(Long entryId)
+ {
+ this.entryId = entryId;
+ }
+
+ public String getCategory()
+ {
+ return category;
+ }
+
+ public void setCategory(String category)
+ {
+ this.category = category;
+ }
+
+ public String getSearchString()
+ {
+ // return null to prevent page param from being encoded when not necessary
+ return searchString == null || searchString.length() == 0 ? null : searchString;
+ }
+
+ public void setSearchString(String searchString)
+ {
+ if (searchString != null)
+ {
+ searchString = searchString.trim();
+ }
+ this.searchString = searchString;
+ }
+
+ public Integer getPage()
+ {
+ // return null to prevent page param from being encoded when not necessary
+ return page == 1 ? null : page;
+ }
+
+ public void setPage(Integer page)
+ {
+ // NOTE if we were to use a primitive propery, page parameters would fail if value is null
+ if (page == null)
+ {
+ this.page = 1;
+ }
+ else if (page < 1)
+ {
+ throw new IllegalArgumentException("Page must be greater than or equal to 1");
+ }
+ else
+ {
+ this.page = page;
+ }
+ }
+
+ public void loadCategories()
+ {
+ categories = retrieveCategories();
+ }
+
+ /**
+ * Init method for the main blog page
+ */
+ public void loadLatestEntries()
+ {
+ loadCategories();
+ entriesForPage = (searchString != null ? retrieveSearchResults() : retrieveLatestEntries());
+ }
+
+ /**
+ * Init method for a category page
+ */
+ public void loadLatestEntriesInCategory()
+ {
+ loadCategories();
+ if (categories.contains(category))
+ {
+ entriesForPage = (searchString != null ? retrieveSearchResultsInCategory() : retrieveLatestEntriesInCategory());
+ }
+ else
+ {
+ category = null;
+ }
+ }
+
+ /**
+ * Init method for an entry page
+ */
+ public void loadEntry()
+ {
+ loadCategories();
+ entry = retrieveSelectedEntry();
+ }
+
+ public boolean search()
+ {
+ page = 1;
+ return true;
+ }
+
+ /**
+ * Retrieves the catagories used in this blog. This method references preloaded
+ * data and is intended to be used in the EL value expressions in the view template.
+ */
+ public List<String> getCategories()
+ {
+ return categories;
+ }
+
+ /**
+ * Retrieves the categories used in this blog other than the selected one. This
+ * method references preloaded data and is intended to be used in the EL value
+ * expressions in the view template.
+ */
+ public List<String> getOtherCategories()
+ {
+ List<String> others = new ArrayList<String>();
+ // defensive here because of postback decodes grrr..
+ if (categories != null)
+ {
+ others.addAll(categories);
+ others.remove(category);
+ }
+ return others;
+ }
+
+ /**
+ * Retrieves the entries loaded for this page. This method references preloaded
+ * data and is intended to be used in EL value expressions in the view template.
+ */
+ public List<BlogEntry> getEntriesForPage()
+ {
+ return entriesForPage;
+ }
+
+ public Set<BlogEntry> getEntriesForPageAsSet()
+ {
+ return new LinkedHashSet(entriesForPage);
+ }
+
+ public int getNumEntriesOnPage()
+ {
+ return entriesForPage.size();
+ }
+
+ /**
+ * Retrieves the entry loaded for this page. This method references preloaded
+ * data and is intended to be used in EL value expressions in the view template.
+ */
+ public BlogEntry getEntry()
+ {
+ return entry;
+ }
+
+ public int getPreviousPageWithFirstPageAsNumber()
+ {
+ assert page > 1;
+ return page - 1;
+ }
+
+ public Integer getPreviousPage()
+ {
+ assert page > 1;
+ return page > 2 ? page - 1 : null;
+ }
+
+ public int getPageWithFirstPageAsNumber()
+ {
+ return page;
+ }
+
+ public int getNextPage()
+ {
+ return page + 1;
+ }
+
+ public boolean isNextPageAvailable()
+ {
+ return nextPageAvailable;
+ }
+
+ public boolean isPreviousPageAvailable()
+ {
+ return page > 1;
+ }
+
+ protected List<BlogEntry> retrieveLatestEntries()
+ {
+ List<BlogEntry> entries = repository.getLatestEntries((page - 1) * PAGE_SIZE, PAGE_SIZE + 1);
+ if (entries.isEmpty() && page > 1)
+ {
+ page = 1;
+ entries = repository.getLatestEntries(0, PAGE_SIZE + 1);
+ }
+
+ return postProcessNavigationProbe(entries);
+ }
+
+ protected List<BlogEntry> retrieveSearchResults()
+ {
+ List<BlogEntry> entries = repository.searchEntries(searchString, (page - 1) * PAGE_SIZE, PAGE_SIZE + 1);
+ if (entries.isEmpty() && page > 1)
+ {
+ page = 1;
+ entries = repository.searchEntries(searchString, 0, PAGE_SIZE + 1);
+ }
+
+ return postProcessNavigationProbe(entries);
+ }
+
+ protected List<BlogEntry> retrieveLatestEntriesInCategory()
+ {
+ List<BlogEntry> entries = repository.getLatestEntries(category, (page - 1) * PAGE_SIZE, PAGE_SIZE + 1);
+ if (entries.isEmpty() && page > 1)
+ {
+ page = 1;
+ entries = repository.getLatestEntries(category, 0, PAGE_SIZE + 1);
+ }
+
+ return postProcessNavigationProbe(entries);
+ }
+
+ protected List<BlogEntry> retrieveSearchResultsInCategory()
+ {
+ List<BlogEntry> entries = repository.searchEntries(searchString, category, (page - 1) * PAGE_SIZE, PAGE_SIZE + 1);
+ if (entries.isEmpty() && page > 1)
+ {
+ page = 1;
+ entries = repository.searchEntries(searchString, category, 0, PAGE_SIZE + 1);
+ }
+
+ return postProcessNavigationProbe(entries);
+ }
+
+ private List<BlogEntry> postProcessNavigationProbe(List<BlogEntry> entries)
+ {
+ if (entries.size() > PAGE_SIZE)
+ {
+ nextPageAvailable = true;
+ entries.remove(entries.size() - 1);
+ }
+ else
+ {
+ nextPageAvailable = false;
+ }
+
+ return entries;
+ }
+
+ protected BlogEntry retrieveSelectedEntry()
+ {
+ return repository.getEntry(entryId);
+ }
+
+ protected List<String> retrieveCategories()
+ {
+ return repository.getCategories();
+ }
+}
Added: examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntry.java
===================================================================
--- examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntry.java (rev 0)
+++ examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntry.java 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,147 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.weld.examples.permalink;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Dan Allen
+ */
+public class BlogEntry
+{
+ private Long id;
+
+ private String author;
+
+ private String category;
+
+ private String title;
+
+ private Date postDate;
+
+ private String body;
+
+ private List<String> tags;
+
+ private List<Comment> comments = new ArrayList<Comment>();
+
+ public BlogEntry()
+ {
+ }
+
+ public BlogEntry(Long id, String author, String category, String title, Date postDate, String body)
+ {
+ this.id = id;
+ this.author = author;
+ this.category = category;
+ this.title = title;
+ this.body = body;
+ this.postDate = postDate;
+ }
+
+ public String getAuthor()
+ {
+ return author;
+ }
+
+ public void setAuthor(String author)
+ {
+ this.author = author;
+ }
+
+ public String getBody()
+ {
+ return body;
+ }
+
+ public void setBody(String body)
+ {
+ this.body = body;
+ }
+
+ public String getCategory()
+ {
+ return category;
+ }
+
+ public void setCategory(String category)
+ {
+ this.category = category;
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public Date getPostDate()
+ {
+ return postDate;
+ }
+
+ public void setPostDate(Date postDate)
+ {
+ this.postDate = postDate;
+ }
+
+ public List<String> getTags()
+ {
+ return tags;
+ }
+
+ public void setTags(List<String> tags)
+ {
+ this.tags = tags;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ public List<Comment> getComments()
+ {
+ return comments;
+ }
+
+ public void setComments(List<Comment> comments)
+ {
+ this.comments = comments;
+ }
+
+ public int getNumComments()
+ {
+ return comments == null ? 0 : comments.size();
+ }
+}
Added: examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntryRepository.java
===================================================================
--- examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntryRepository.java (rev 0)
+++ examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/BlogEntryRepository.java 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,264 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.weld.examples.permalink;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+
+/**
+ * @author Dan Allen
+ */
+public
+@ApplicationScoped
+class BlogEntryRepository
+{
+ private static AtomicLong uniqueEntryId = new AtomicLong(0);
+
+ private static AtomicLong uniqueCommentId = new AtomicLong(0);
+
+ private final List<BlogEntry> entries;
+
+ private DateFormat dateParser;
+
+ public BlogEntryRepository()
+ {
+ entries = new ArrayList<BlogEntry>();
+ }
+
+ @PostConstruct
+ public void seed()
+ {
+ entries.add(new BlogEntry(uniqueEntryId.incrementAndGet(), "Dan", "General", "My first post", parseDate("15/01/09 13:30"), "This is the obligatory first post."));
+ entries.add(new BlogEntry(uniqueEntryId.incrementAndGet(), "Dan", "JSF 2", "View parameters", parseDate("16/01/09 15:12"), "One of the new features in JSF 2 is view parameters. If you are familiar with Seam, you will recognize them as page parameters. They bring the value binding concept to GET requests by allowing you to associate a request parameter with a EL value binding expression. You can witness view parameters in action in this demo. View parameters are especially useful for ensuring that the URL is always bookmarkable throughout the user's browsing session."));
+ entries.add(new BlogEntry(uniqueEntryId.incrementAndGet(), "Dan", "JSF 2", "Bookmarkable links", parseDate("18/01/09 14:45"), "JSF finally has bookmarkable links. No more complaining that \"everything is a POST!\""));
+ entries.add(new BlogEntry(uniqueEntryId.incrementAndGet(), "Dan", "Java EE", "What's new in Java EE 6", parseDate("20/01/09 08:15"), "JSF 2, JPA 2, EJB 3.1, Java Contexts and Dependency Injection (formally Web Beans) and more!"));
+ entries.add(new BlogEntry(uniqueEntryId.incrementAndGet(), "Dan", "JSF 2", "Annotation nation", parseDate("22/01/09 10:34"), "You can finally free yourself from the tangles of XML and use annotations to define your managed beans. You put @ManagedBean on a class to define a managed bean and you annotate a field with @ManagedProperty to wire two beans together. If those annotations aren't enough to satisfy you, then check out JSR-299: Java Contexts and Dependency Injection. That spec uses annotations extensively and is a drop-in replacement for the JSF managed bean facility...and a much more capabable one at that!"));
+ entries.add(new BlogEntry(uniqueEntryId.incrementAndGet(), "Dan", "JSF 2", "Mojarra == RI", parseDate("25/01/09 11:00"), "The JSF reference implementation finally has a name: Mojarra. Surprise, it's the name of a fish."));
+ Collections.sort(entries, new Comparator<BlogEntry>()
+ {
+ public int compare(BlogEntry a, BlogEntry b)
+ {
+ return b.getPostDate().compareTo(a.getPostDate());
+ }
+ });
+ }
+
+ public List<BlogEntry> searchEntries(String searchString, int offset, int count)
+ {
+ if (count == 0)
+ {
+ return Collections.<BlogEntry>emptyList();
+ }
+
+ if (searchString == null || searchString.trim().length() == 0)
+ {
+ return getLatestEntries(offset, count);
+ }
+
+ searchString = searchString.trim().toLowerCase();
+
+ List<BlogEntry> results = new ArrayList<BlogEntry>();
+ int idx = 0;
+ for (BlogEntry entry : entries)
+ {
+ if ((entry.getTitle().toLowerCase().contains(searchString) || entry.getBody().toLowerCase().contains(searchString)) &&
+ idx++ >= offset)
+ {
+ results.add(entry);
+ if (results.size() == count)
+ {
+ return results;
+ }
+ }
+ }
+
+ return results;
+ }
+
+ public List<BlogEntry> searchEntries(String searchString, String category, int offset, int count)
+ {
+ if (count == 0)
+ {
+ return Collections.<BlogEntry>emptyList();
+ }
+
+ if (category == null || category.trim().length() == 0)
+ {
+ return searchEntries(searchString, offset, count);
+ }
+
+ if (searchString == null || searchString.trim().length() == 0)
+ {
+ return getLatestEntries(offset, count);
+ }
+
+ category = category.trim();
+ searchString = searchString.trim().toLowerCase();
+
+ List<BlogEntry> results = new ArrayList<BlogEntry>();
+ int idx = 0;
+ for (BlogEntry entry : entries)
+ {
+ if (entry.getCategory().equals(category) &&
+ (entry.getTitle().toLowerCase().contains(searchString) || entry.getBody().toLowerCase().contains(searchString)) &&
+ idx++ >= offset)
+ {
+ results.add(entry);
+ if (results.size() == count)
+ {
+ return results;
+ }
+ }
+ }
+
+ return results;
+ }
+
+ public List<BlogEntry> getLatestEntries(String category, int offset, int count)
+ {
+ if (count == 0)
+ {
+ return Collections.<BlogEntry>emptyList();
+ }
+
+ if (category == null || category.trim().length() == 0)
+ {
+ return getLatestEntries(offset, count);
+ }
+
+ category = category.trim();
+
+ List<BlogEntry> results = new ArrayList<BlogEntry>();
+ int idx = 0;
+ for (BlogEntry entry : entries)
+ {
+ if (entry.getCategory().equals(category) && idx++ >= offset)
+ {
+ results.add(entry);
+ if (results.size() == count)
+ {
+ return results;
+ }
+ }
+ }
+
+ return results;
+ }
+
+ public List<BlogEntry> getLatestEntries(int offset, int count)
+ {
+ if (count == 0)
+ {
+ return Collections.<BlogEntry>emptyList();
+ }
+
+ List<BlogEntry> results = new ArrayList<BlogEntry>();
+ int idx = 0;
+ for (BlogEntry entry : entries)
+ {
+ if (idx++ >= offset)
+ {
+ results.add(entry);
+ if (results.size() == count)
+ {
+ return results;
+ }
+ }
+ }
+
+ return results;
+ }
+
+ public BlogEntry getEntry(Long entryId)
+ {
+ // TODO index the entries by id
+ for (BlogEntry entry : entries)
+ {
+ if (entry.getId().equals(entryId))
+ {
+ return entry;
+ }
+ }
+
+ return null;
+ }
+
+ public List<String> getCategories()
+ {
+ // TODO index list of categories
+ List<String> categories = new ArrayList<String>();
+ for (BlogEntry entry : entries)
+ {
+ if (!categories.contains(entry.getCategory()))
+ {
+ categories.add(entry.getCategory());
+ }
+ }
+
+ Collections.sort(categories);
+ return categories;
+ }
+
+ public void addComment(Comment comment, Long entryId)
+ {
+ addComment(comment, getEntry(entryId));
+ }
+
+ public void addComment(Comment comment, BlogEntry entry)
+ {
+ comment.setId(uniqueCommentId.incrementAndGet());
+ comment.setPostDate(new Date());
+ comment.setEntry(entry);
+ synchronized (entry)
+ {
+ // clone to break reference to the managed bean
+ entry.getComments().add(new Comment(comment));
+ }
+ }
+
+ private Date parseDate(String dateString)
+ {
+ if (dateParser == null)
+ {
+ dateParser = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.UK);
+ }
+
+ try
+ {
+ return dateParser.parse(dateString);
+ }
+ catch (ParseException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
Added: examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Comment.java
===================================================================
--- examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Comment.java (rev 0)
+++ examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/Comment.java 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,130 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.weld.examples.permalink;
+
+import java.util.Date;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+/**
+ * @author Dan Allen
+ */
+public
+@Named
+@RequestScoped
+class Comment
+{
+ private Long id;
+
+ private BlogEntry entry;
+
+ private Date postDate;
+
+ private String author;
+
+ private String body;
+
+ public Comment()
+ {
+ }
+
+ public Comment(Long id, BlogEntry entry, String author, Date postDate, String body)
+ {
+ this.id = id;
+ this.entry = entry;
+ this.author = author;
+ this.postDate = postDate;
+ this.body = body;
+ }
+
+ public Comment(Comment other)
+ {
+ this.id = other.getId();
+ this.entry = other.getEntry();
+ this.author = other.getAuthor();
+ this.postDate = other.getPostDate();
+ this.body = other.getBody();
+ }
+
+ public BlogEntry getEntry()
+ {
+ return entry;
+ }
+
+ public void setEntry(BlogEntry entry)
+ {
+ this.entry = entry;
+ }
+
+ public Date getPostDate()
+ {
+ return postDate;
+ }
+
+ public void setPostDate(Date postDate)
+ {
+ this.postDate = postDate;
+ }
+
+ public String getAuthor()
+ {
+ return author;
+ }
+
+ public void setAuthor(String author)
+ {
+ this.author = author;
+ }
+
+ public String getBody()
+ {
+ return body;
+ }
+
+ public void setBody(String body)
+ {
+ this.body = body;
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Comment@").append(hashCode()).append("{");
+ sb.append("id=").append(id).append("; ");
+ sb.append("author=").append(author).append("; ");
+ sb.append("body=").append(body);
+ sb.append("}");
+ return sb.toString();
+ }
+}
Added: examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/CommentBoard.java
===================================================================
--- examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/CommentBoard.java (rev 0)
+++ examples/trunk/jsf/permalink/src/main/java/org/jboss/weld/examples/permalink/CommentBoard.java 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.weld.examples.permalink;
+
+import javax.faces.context.FacesContext;
+import javax.faces.application.FacesMessage;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * @author Dan Allen
+ */
+public
+@Named
+@RequestScoped
+class CommentBoard
+{
+ @Inject BlogEntryRepository repository;
+
+ @Inject Comment comment;
+
+ @Inject Blog blog;
+
+ public Boolean post()
+ {
+ if (comment == null || blog == null)
+ {
+ return null;
+ }
+
+ BlogEntry entry = repository.getEntry(blog.getEntryId());
+ if (entry == null)
+ {
+ return null;
+ }
+
+ repository.addComment(comment, entry);
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ ctx.addMessage(null, new FacesMessage("Thanks for leaving a comment!"));
+ // FIXME doesn't seem to be working; must investigate
+ ctx.getExternalContext().getFlash().setKeepMessages(true);
+ return true;
+ }
+}
Added: examples/trunk/jsf/permalink/src/main/resources/META-INF/beans.xml
===================================================================
Added: examples/trunk/jsf/permalink/src/main/resources/log4j.xml
===================================================================
--- examples/trunk/jsf/permalink/src/main/resources/log4j.xml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/resources/log4j.xml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{2}] %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <priority value="INFO"/>
+ <appender-ref ref="CONSOLE"/>
+ </root>
+
+</log4j:configuration>
Added: examples/trunk/jsf/permalink/src/main/webapp/META-INF/context.xml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/META-INF/context.xml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/META-INF/context.xml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Context>
+ <Manager pathname=""/> <!-- disables storage of sessions across restarts -->
+</Context>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/faces-config.xml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/faces-config.xml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/faces-config.xml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<faces-config version="2.0"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
+
+ <navigation-rule>
+ <from-view-id>*</from-view-id>
+ <navigation-case>
+ <from-action>#{blog.search}</from-action>
+ <to-view-id>/home.xhtml</to-view-id>
+ <redirect include-view-params="true"/>
+ </navigation-case>
+ </navigation-rule>
+
+ <navigation-rule>
+ <from-view-id>/category.xhtml</from-view-id>
+ <navigation-case>
+ <from-action>#{blog.search}</from-action>
+ <to-view-id>#{view.viewId}</to-view-id>
+ <redirect include-view-params="true"/>
+ </navigation-case>
+ <navigation-case>
+ <from-action>#{blog.loadLatestEntriesInCategory}</from-action>
+ <if>#{blog.category eq null}</if>
+ <to-view-id>/home.xhtml</to-view-id>
+ <redirect/>
+ </navigation-case>
+ </navigation-rule>
+
+ <navigation-rule>
+ <from-view-id>/entry.xhtml</from-view-id>
+ <navigation-case>
+ <from-action>#{commentBoard.post}</from-action>
+ <to-view-id>#{view.viewId}</to-view-id>
+ <redirect include-view-params="true"/>
+ </navigation-case>
+ </navigation-rule>
+
+</faces-config>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/categories.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/categories.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/categories.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <h2>Categories</h2>
+ <ul>
+ <ui:repeat var="_category" value="#{blog.categories}">
+ <li>
+ <h:link outcome="category" value="#{_category}">
+ <f:param name="name" value="#{_category}"/>
+ </h:link>
+ </li>
+ </ui:repeat>
+ </ul>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/comments.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/comments.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/comments.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <ul id="comments" class="post-comments clear">
+ <h3>#{_entry.numComments} Comment#{_entry.numComments != 1 ? 's' : ''}</h3>
+ <ui:repeat var="_comment" varStatus="it" value="#{_entry.comments}">
+ <li class="comment clear #{it.even ? 'alt' : ''}">
+ <cite class="comment-author">#{_comment.author}</cite>
+ <div class="comment-content"><p>#{_comment.body}</p></div>
+ </li>
+ </ui:repeat>
+ </ul>
+ <h3>Any thoughts?</h3>
+ <h:form id="comment" prependId="false">
+ <p>
+ <h:inputText id="author" value="#{comment.author}" size="20" tabindex="1" required="true" label="Author"/>
+ <h:outputLabel for="author" value="Name (required)"/>
+ <br/>
+ <h:message for="author" style="color: #FF0000;"/>
+ </p>
+ <p>
+ <h:inputTextarea id="body" value="#{comment.body}" cols="60" rows="7" tabindex="2" required="true" label="Comment text"/>
+ <h:message for="body" style="color: #FF0000;"/>
+ </p>
+ <p>
+ <h:commandButton id="post" action="#{commentBoard.post}" tabindex="3" value="Submit"/>
+ </p>
+ </h:form>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/commonViewParams.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/commonViewParams.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/commonViewParams.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core">
+
+ <f:viewParam name="page" value="#{blog.page}"/>
+ <f:viewParam name="q" value="#{blog.searchString}"/>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryContent.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryContent.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryContent.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jsp/jstl/core"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <div class="post">
+ <div class="post-title">
+ <h2 id="entry-#{_entry.id}">#{_entry.title}</h2>
+ <h3>
+ Posted by #{_entry.author}
+ on #{' '}<h:outputText value="#{_entry.postDate}"><f:convertDateTime type="date" dateStyle="long"/></h:outputText>
+ at #{' '}<h:outputText value="#{_entry.postDate}"><f:convertDateTime type="time" timeStyle="short"/></h:outputText>
+ in #{' '}<h:link outcome="category" value="#{_entry.category}"><f:param name="name" value="#{_entry.category}"/></h:link>
+ </h3>
+ </div>
+ <div class="post-content">
+ <p>#{_entry.body}</p>
+ </div>
+ <div class="post-links">
+ <c:if test="#{view.viewId != '/entry.xhtml'}">
+ <h:link outcome="entry" value="View Entry" includeViewParams="true" title="View this entry without losing your current browsing state."
+ ><f:param name="id" value="#{_entry.id}"
+ /></h:link>
+ <span style="font-size: smaller;">|</span>
+ </c:if>
+ #{' '}<h:link outcome="entry" value="Permalink" title="A bookmarkable link for this entry."
+ ><f:param name="id" value="#{_entry.id}"
+ /></h:link>
+ </div>
+ <c:if test="#{view.viewId == '/entry.xhtml'}">
+ <ui:include src="comments.xhtml"/>
+ </c:if>
+ </div>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryList.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryList.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/entryList.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jsp/jstl/core"
+ xmlns:fn="http://java.sun.com/jsp/jstl/functions"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <c:if test="#{view.viewId == '/category.xhtml'}">
+ <div class="category">
+ <ui:remove><span>#{not empty blog.category ? fn:concat('Category: ', blog.category) : 'INVALID CATEGORY!'}</span></ui:remove>
+ <span>#{not empty blog.category ? 'Category: ' : ''}#{not empty blog.category ? blog.category : 'INVALID CATEGORY!'}</span>
+ </div>
+ </c:if>
+ <ui:repeat var="_entry" value="#{blog.entriesForPage}">
+ <ui:include src="entryContent.xhtml"/>
+ </ui:repeat>
+ <div class="post-navigation">
+ <span class="arrow">««</span> #{' '}<h:link id="first" value="First Page" disabled="#{not blog.previousPageAvailable}" includeViewParams="true"
+ ><f:param name="page" disable="true"
+ /></h:link>
+ <span class="arrow">«</span> #{' '}<h:link id="previous" value="Newer Entries" disabled="#{not blog.previousPageAvailable}" includeViewParams="true"
+ ><f:param name="page" value="#{blog.previousPage}"
+ /></h:link>
+ <span style="font-size: smaller;">–</span>
+ #{' '}<h:link outcome="#{view.viewId}" id="next" value="Older Entries" disabled="#{not blog.nextPageAvailable}" includeViewParams="true"
+ ><f:param name="page" value="#{blog.nextPage}"
+ /></h:link> <span class="arrow">»</span>
+ </div>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/otherCategories.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/otherCategories.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/otherCategories.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <h2>Other Categories</h2>
+ <ul>
+ <ui:repeat var="_category" value="#{blog.otherCategories}">
+ <li>
+ <h:link outcome="category" value="#{_category}">
+ <f:param name="name" value="#{_category}"/>
+ </h:link>
+ </li>
+ </ui:repeat>
+ </ul>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/singleEntry.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/singleEntry.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/fragments/singleEntry.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+
+ <ui:remove><!-- The check for phase prevents a "ghost" form submit --></ui:remove>
+ <h:panelGroup rendered="#{facesContext.currentPhaseId.ordinal == 6 and empty blog.entry}">
+ <p>Sorry, no post exists with that identifier.</p>
+ </h:panelGroup>
+ <h:panelGroup rendered="#{not empty blog.entry or facesContext.currentPhaseId.ordinal != 6}">
+ <ui:include src="entryContent.xhtml">
+ <ui:param name="_entry" value="#{blog.entry}"/>
+ </ui:include>
+ </h:panelGroup>
+ <div class="post-navigation">
+ <h:panelGroup rendered="#{not empty blog.category}">
+ <h:button outcome="category" value="Back to #{blog.category}" fragment="entry-#{blog.entry.id}" includeViewParams="true"/>
+ </h:panelGroup>
+ <h:panelGroup rendered="#{empty blog.category}">
+ <h:button outcome="home" value="Back to main page" fragment="entry-#{blog.entry.id}" includeViewParams="true"/>
+ </h:panelGroup>
+ #{' '}<h:button outcome="entry" value="Hide comments" disabled="true" includeViewParams="true">
+ <f:param name="comments" value="false"/>
+ </h:button>
+ <ui:remove><!--
+ <h:panelGroup rendered="#{not empty blog.category}">
+ « <h:link outcome="category" value="Back to #{blog.category}" includeViewParams="true"/>
+ </h:panelGroup>
+ <h:panelGroup rendered="#{empty blog.category}">
+ « <h:link outcome="home" value="Back to main page" includeViewParams="true"/>
+ </h:panelGroup>
+ --></ui:remove>
+ </div>
+
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/jetty-env.xml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/jetty-env.xml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/jetty-env.xml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
+ "http://jetty.mortbay.org/configure.dtd">
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<Configure id="webAppCtx" class="org.mortbay.jetty.webapp.WebAppContext">
+</Configure>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/layout/template.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/layout/template.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/layout/template.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:h="http://java.sun.com/jsf/html">
+ <f:view>
+ <ui:insert name="viewMetadata"/>
+ <head>
+ <title>Permalink</title>
+ <link rel="shortcut icon" href="#{request.contextPath}/favicon.ico"/>
+ <link rel="stylesheet" href="#{request.contextPath}/css/style.css" type="text/css" media="screen" />
+ <!--[if lte IE 6]>
+ <link rel="stylesheet" href="#{request.contextPath}/css/legacy.css" type="text/css" media="screen" title="no title" charset="utf-8" />
+ <![endif]-->
+ </head>
+ <body>
+ <div id="header">
+ <div class="inner clear">
+ <h1><h:link outcome="home">Permalink</h:link></h1>
+ <p>Direct links to the news you crave</p>
+ </div>
+ </div>
+ <div id="search">
+ <div class="inner clear">
+ <a id="rss-link" href="http://in.relation.to/service/Feed/atom"><strong>Subscribe to this Feed</strong></a>
+ <a id="technorati-link" href="http://technorati.com/faves?add=http://in.relation.to"><strong>Add to your Favorites</strong></a>
+ <h:form id="search" prependId="false">
+ <div>
+ <label for="q">Search</label>
+ #{' '}<h:inputText id="q" value="#{blog.searchString}"/><h:commandButton id="s" action="#{blog.search}" image="/img/search.png" title="Search"/>
+ </div>
+ </h:form>
+ </div>
+ </div>
+ <div id="wrapper" class="clear">
+ <div id="content">
+ <h:messages id="messages" globalOnly="true"/>
+ <ui:insert name="content">
+ <ui:include src="../fragments/entryList.xhtml"/>
+ </ui:insert>
+ </div>
+ <ul id="sidebar">
+ <li>
+ <ui:insert name="categories">
+ <ui:include src="../fragments/categories.xhtml"/>
+ </ui:insert>
+ </li>
+ <li>
+ <h2>Blogroll</h2>
+ <ul>
+ <li><a href="http://in.relation.to">In Relation To...</a></li>
+ <li><a href="http://blogs.steeplesoft.com">Coming Up for Air</a></li>
+ <li><a href="http://weblogs.java.net/blog/edburns">Ed Burn's Blog</a></li>
+ <li><a href="http://blogs.sun.com/rlubke">Ryan Lubke's Blog</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ <div id="footer">
+ <p id="blog-name">Permalink JSF Demo</p>
+ <p id="webrevolutionary-link">
+ <a href="http://webrevolutionary.com/coldblue/">ColdBlue</a> v1.0 -
+ A theme by <a href="http://webrevolutionary.com/">WebRevolutionary</a> &
+ <a href="http://www.forwebdesigners.com/">ForWebdesigners</a>
+ </p>
+ </div>
+ </body>
+ </f:view>
+</html>
Added: examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/web.xml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/web.xml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/WEB-INF/web.xml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+
+ <display-name>Weld Permalink Example (Servlet Environment)</display-name>
+
+ <context-param>
+ <param-name>facelets.DEVELOPMENT</param-name>
+ <param-value>true</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>Faces Servlet</servlet-name>
+ <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Faces Servlet</servlet-name>
+ <url-pattern>*.jsf</url-pattern>
+ </servlet-mapping>
+
+ <session-config>
+ <session-timeout>10</session-timeout>
+ </session-config>
+
+</web-app>
Added: examples/trunk/jsf/permalink/src/main/webapp/category.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/category.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/category.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ template="/WEB-INF/layout/template.xhtml">
+ <ui:define name="viewMetadata">
+ <f:metadata>
+ <f:viewParam name="name" value="#{blog.category}"/>
+ <ui:include src="/WEB-INF/fragments/commonViewParams.xhtml"/>
+ <f:event type="preRenderView" listener="#{blog.loadLatestEntriesInCategory}"/>
+ </f:metadata>
+ </ui:define>
+ <ui:define name="categories">
+ <ui:include src="/WEB-INF/fragments/otherCategories.xhtml"/>
+ </ui:define>
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/css/legacy.css
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/css/legacy.css (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/css/legacy.css 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,6 @@
+.clear {
+ height: 1px;
+}
+body {
+ font-size: 62.5%;
+}
Added: examples/trunk/jsf/permalink/src/main/webapp/css/style.css
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/css/style.css (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/css/style.css 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,466 @@
+/*
+Some Aspects Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.2.2
+*/
+html{overflow-y: scroll;}
+body{font:Arial,sans-serif;*font-size:small;*font:x-small;}table{font-size:inherit;font:100%;}select,input,textarea{font:99% arial,helvetica,clean,sans-serif;}pre,code{font:115% monospace;*font-size:100%;}body *{line-height:1.22em;}
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;}
+abbr,acronym{border-bottom:1px dotted #000;}
+em{font-style: italic;}
+strong{font-weight: bold;}
+/* Utility Classes */
+.clear:after{content:'.';display:block;height:0;font-size:0;clear:both;visibility:hidden;}
+.clear{display:inline-block;}
+/* \*/
+.clear{display:block;}
+/* */
+.image{display:block;font-size:0;text-indent:-9999px;outline:none;}
+/*
+Theme Name: ColdBlue
+Theme URI: http://webrevolutionary.com/coldblue/
+Description: ColdBlue - A WordPress theme created by WebRevolutionary.
+Version: 1.2
+Author: WebRevolutionary
+Author URI: http://webrevolutionary.com/
+*/
+body {
+ text-align: center;
+ color: #333;
+ background: #28313a url(../img/bodybg.gif) repeat-x top;
+ font-size: 13px;
+ font-family: Helvetica, Arial, sans-serif;
+}
+div#header {
+ background: #3776bd url(../img/headerbg.gif) repeat-x bottom;
+ width: 100%;
+ border-bottom: 1px solid #3776bd;
+}
+div#search {
+ background: #000;
+ width: 100%;
+}
+div.inner {
+ width: 840px;
+ margin: auto;
+ text-align: left;
+ padding: 10px 0;
+}
+div#header h1 {
+ font-size: 23px;
+ font-weight: bold;
+ float: left;
+ width: 40%;
+ text-shadow: 1px 0px #2B4462;
+ letter-spacing: -1px;
+}
+div#header h1 a {
+ color: #fff;
+ text-decoration: none;
+}
+div#header p {
+ color: #FFFFFF;
+ clear: left;
+ margin: 0;
+}
+ul#navigation {
+ float: right;
+ width: 50%;
+ position: relative;
+ top: 7px;
+ text-align: right;
+}
+ul#navigation li {
+ display: inline;
+}
+ul#navigation li a {
+ color: #BFDCFE;
+ text-decoration: none;
+ font-size: 16px;
+ font-weight: bold;
+ padding: 10px;
+ text-shadow: 1px 0px #2B4462;
+}
+ul#navigation li.active a {
+ color: #BFDCFE;
+}
+ul#navigation li a:hover {
+ color: #fff;
+ text-decoration: underline;
+}
+div#search label {
+ font-weight: bold;
+ color: #666666;
+ padding-right: 3px;
+}
+div#search form {
+ padding-top: 2px;
+ font-size: 14px;
+ width: 40%;
+ float: right;
+ text-align: right;
+}
+div#search form * {
+ vertical-align: middle;
+}
+input#q {
+ width: 140px;
+ border: 0;
+ padding: 2px 1px;
+}
+input#s {
+ background-color: #FFFFFF;
+ padding: 2px;
+}
+ul#sidebar input#s {
+ width: 100px;
+}
+a#rss-link, a#technorati-link {
+ display: block;
+ float: left;
+ color: #333;
+ font-size: 13px;
+ font-weight: bold;
+ position: relative;
+ top: 4px;
+ text-decoration: none;
+ margin: 0 20px 0 0;
+}
+a#rss-link {
+ background: url(../img/rss.gif) no-repeat left center;
+ padding: 0 0 1px 17px;
+}
+a#technorati-link {
+ background: url(../img/technorati.gif) no-repeat left center;
+ padding: 0 0 1px 19px;
+}
+a#rss-link strong, a#technorati-link strong {
+ color: #666!important;
+ border-bottom: 1px dotted #222;
+}
+a#rss-link:hover strong, a#technorati-link:hover strong {
+ color: #ccc!important;
+ border-bottom: 1px solid #333;
+}
+div#wrapper {
+ text-align: left;
+ width: 800px;
+ padding: 20px;
+ margin: auto;
+ /*margin-top: 1.25em;*/
+ background: #fff url(../img/wrapper.gif) repeat-y right;
+ background-position: -60px 0px;
+ border-right: 2px solid #242c34;
+ border-left: 2px solid #242c34;
+}
+div#content {
+ width: 500px;
+ float: left;
+ padding: 0 30px 0 0;
+}
+#messages {
+ color: #9E6B31;
+ margin-bottom: 10px;
+ font-size: 15px;
+}
+.category {
+ background-color: #EAF3F9;
+ background: #99CCFF url(../img/wgradient.png) repeat-x;
+ border-top: 1px solid #666666;
+ border-bottom: 1px solid #666666;
+ padding: 5px 10px;
+ margin-bottom: 1em;
+ text-align: center;
+ font-weight: bold;
+ letter-spacing: 3px;
+ text-align: right;
+}
+ul#sidebar {
+ display: block;
+ width: 240px;
+ float: left;
+ padding: 10px 0 0 30px;
+ font-size: 13px;
+}
+ul#sidebar h2 {
+ font-size: 20px;
+}
+ul#sidebar li {
+ margin: 0 0 20px;
+ padding: 0 0 10px;
+ border-bottom: 1px dotted #ccc;
+}
+ul#sidebar li ul li {
+ font-size: 13px!important;
+ margin: 0;
+ border: none;
+}
+ul#sidebar ul.block-list li a {
+ display: block;
+ padding: 7px 0;
+ border-bottom: 1px dotted #ccc;
+ text-decoration: none;
+}
+ul#sidebar ul.block-list li a:hover {
+ text-decoration: none;
+}
+h2, h3, h4, h5, h6 {
+ color: #000;
+}
+h2 {
+ font-size: 30px;
+ margin: 0 0 8px!important;
+ letter-spacing: -1px;
+}
+h2 a {
+ color: #000;
+ text-decoration: none;
+}
+h2 a:hover {
+ color: #000;
+ text-decoration: underline;
+}
+h3 {
+ font-size: 18px;
+ margin: 0 0 8px;
+}
+div.post h3 {
+ margin: 0 0 2px;
+}
+h4 {
+ font-size: 16px;
+}
+div.post-title {
+ margin: 0 0 10px;
+}
+div.post-title h2 {
+ margin: 0;
+}
+div.post-title h3 {
+ color: #999;
+ font-size: 13px;
+ /* trying out */
+ font-style: italic;
+ font-family: Arial, sans-serif;
+}
+div.post-title h3 a {
+ color: #666;
+ text-decoration: none;
+ border-bottom: 1px dotted #ccc;
+}
+div.post-title h3 a:hover {
+ border-bottom: 1px solid #aaa;
+ color: #444;
+}
+p {
+ margin: 0 0 20px;
+ font-size: 13px;
+ line-height: 20px;
+}
+p img {
+ background: #fff;
+ padding: 5px;
+ border: 1px solid #999;
+ border-top: 1px solid #ccc;
+ border-left: 1px solid #ccc;
+}
+p a:hover img {
+ border: 1px solid #777;
+ border-top: 1px solid #aaa;
+ border-left: 1px solid #aaa;
+}
+form p {
+ margin-bottom: 10px;
+}
+img.float-left, img.alignleft {
+ display: block;
+ float: left;
+ clear: left;
+ margin: 0 24px 12px 0;
+}
+img.float-right, img.alignright {
+ display: block;
+ float: right;
+ clear: right;
+ margin: 0 0 12px 12px;
+}
+img.center, img.centered {
+ display: block;
+ clear: both;
+ margin: auto;
+}
+.alignleft {
+ float: left;
+}
+.alignright {
+ float: right;
+}
+div.post-content ul, div.post-content ol {
+ margin: 5px 0 12px 24px;
+ list-style: disc;
+ font-size: 13px;
+}
+div.post-content ol {
+ list-style: decimal;
+}
+div.post-links {
+ padding-left: 2px;
+ margin-bottom: 5px;
+}
+a {
+ color: #0078C8;
+}
+a:hover {
+ color: #0095f8;
+}
+blockquote {
+ font-size: 15px!important;
+ font-family: Georgia, Times, 'Times New Roman', serif;
+ color: #444;
+ font-style: italic;
+ margin: 0 0 0 22px;
+ line-height: 24px!important;
+ display: block;
+}
+blockquote p {
+ font-size: 15px!important;
+ line-height: 24px!important;
+}
+cite {
+ text-align: right;
+ float: right;
+ color: #aaa;
+}
+cite a {
+ color: #aaa;
+ text-decoration: none;
+}
+cite a:hover {
+ color: #999;
+ text-decoration: underline;
+}
+code {
+ font-size: 130%;
+ background: #fafafa;
+}
+code.block {
+ display: block;
+ padding: 10px;
+}
+div.post {
+ padding: 0 0 10px;
+ margin: 0 0 25px;
+ border-bottom: 1px dotted #ccc;
+}
+ul.post-comments {
+ margin: 26px 0;
+}
+ul.post-comments h3 {
+ margin: 0 0 5px;
+}
+li.comment {
+ display: block;
+ padding: 20px 20px 0;
+ border-bottom: 1px dotted #ccc;
+ background: #fafafa;
+}
+li.comment.alt {
+ background: #fff;
+}
+cite.comment-author {
+ text-align: left;
+ float: left;
+ color: #000;
+ font-size: 16px;
+ font-weight: bold;
+ width: 150px;
+ clear: left;
+ display: block;
+}
+cite.comment-author a {
+ color: #333;
+ text-decoration: none;
+}
+cite.comment-author a:hover {
+ text-decoration: underline;
+}
+cite.comment-author img {
+ position: relative;
+ top: 6px;
+ margin: 0 10px 0 0;
+}
+div.comment-content {
+ display: block;
+ width: 300px;
+ float: left;
+ padding: 0 0 0 10px;
+}
+div.post-navigation .arrow {
+ font-size: 1.1em;
+}
+table#wp-calendar {
+ margin: auto;
+ text-align: center;
+}
+table#wp-calendar caption {
+ font-size: 14px;
+ text-align: center;
+ color: #999;
+}
+table#wp-calendar td {
+ padding: 5px;
+ font-size: 13px;
+ text-align: center;
+}
+table#wp-calendar th {
+ font-size: 14px;
+ padding: 5px;
+ text-align: center;
+ font-weight: bold;
+}
+table#wp-calendar td a {
+ font-weight: bold;
+}
+a abbr, a acronym {
+ border: none;
+}
+div#footer {
+ clear: both;
+ background: #000;
+ padding: 25px 10px 15px;
+ display: block;
+ width: 820px;
+ margin: auto;
+ border-right: 2px solid #242c34;
+ border-left: 2px solid #242c34;
+ text-align: left;
+}
+div#footer p {
+ font-size: 12px;
+ margin: 0 0 5px 20px;
+ color: #555;
+}
+div#footer a {
+ color: #ccc;
+ text-decoration: none;
+ border-bottom: 1px solid #222;
+ font-weight: bold;
+}
+div#footer a:hover {
+ color: #fff;
+ border-bottom: 1px solid #444;
+}
+div#footer p#blog-name {
+ font-size: 16px;
+ color: #aaa;
+}
+div#footer p#webrevolutionary-link {
+ color: #333;
+}
+div#footer p#webrevolutionary-link a {
+ color: #444;
+}
+div#footer p#webrevolutionary-link a:hover {
+ color: #666;
+}
Added: examples/trunk/jsf/permalink/src/main/webapp/entry.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/entry.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/entry.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ template="/WEB-INF/layout/template.xhtml">
+ <ui:define name="viewMetadata">
+ <f:metadata>
+ <f:viewParam name="id" value="#{blog.entryId}"/>
+ <f:viewParam name="category" value="#{blog.category}"/>
+ <ui:include src="/WEB-INF/fragments/commonViewParams.xhtml"/>
+ <f:event type="preRenderView" listener="#{blog.loadEntry}"/>
+ </f:metadata>
+ </ui:define>
+ <ui:define name="content">
+ <ui:include src="/WEB-INF/fragments/singleEntry.xhtml"/>
+ </ui:define>
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/favicon.ico
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/favicon.ico
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/home.xhtml
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/home.xhtml (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/home.xhtml 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ JBoss, Home of Professional Open Source
+ Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ by the @authors tag. See the copyright.txt in the distribution for a
+ full listing of individual contributors.
+
+ This is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this software; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+-->
+<ui:composition xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:f="http://java.sun.com/jsf/core"
+ template="/WEB-INF/layout/template.xhtml">
+ <ui:define name="viewMetadata">
+ <f:metadata>
+ <ui:include src="/WEB-INF/fragments/commonViewParams.xhtml"/>
+ <f:event type="preRenderView" listener="#{blog.loadLatestEntries}"/>
+ </f:metadata>
+ </ui:define>
+</ui:composition>
Added: examples/trunk/jsf/permalink/src/main/webapp/img/bodybg.gif
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/bodybg.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/headerbg.gif
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/headerbg.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/rss.gif
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/rss.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/search.png
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/search.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/searchbg.gif
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/searchbg.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/technorati.gif
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/technorati.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/wgradient.png
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/wgradient.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/img/wrapper.gif
===================================================================
(Binary files differ)
Property changes on: examples/trunk/jsf/permalink/src/main/webapp/img/wrapper.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: examples/trunk/jsf/permalink/src/main/webapp/index.html
===================================================================
--- examples/trunk/jsf/permalink/src/main/webapp/index.html (rev 0)
+++ examples/trunk/jsf/permalink/src/main/webapp/index.html 2009-10-27 18:51:33 UTC (rev 4353)
@@ -0,0 +1 @@
+<html><head><meta http-equiv="Refresh" content="0; URL=home.jsf"/></head></html>
15 years, 1 month
Weld SVN: r4352 - in doc/trunk/reference/en-US: images and 1 other directory.
by weld-commits@lists.jboss.org
Author: dan.j.allen
Date: 2009-10-27 14:36:17 -0400 (Tue, 27 Oct 2009)
New Revision: 4352
Added:
doc/trunk/reference/en-US/images/m2eclipse-wicket-numberguess-import.png
Modified:
doc/trunk/reference/en-US/Author_Group.xml
doc/trunk/reference/en-US/Book_Info.xml
doc/trunk/reference/en-US/environments.xml
doc/trunk/reference/en-US/example.xml
doc/trunk/reference/en-US/gettingstarted.xml
doc/trunk/reference/en-US/intro.xml
doc/trunk/reference/en-US/master.xml
doc/trunk/reference/en-US/part1.xml
Log:
first round of updates title, part1, example, intro and getting started, as well as some tweaks here and there
Modified: doc/trunk/reference/en-US/Author_Group.xml
===================================================================
--- doc/trunk/reference/en-US/Author_Group.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/Author_Group.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -6,7 +6,7 @@
<surname>King</surname>
<affiliation>
<jobtitle>JSR-299 specification lead</jobtitle>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</author>
<author>
@@ -15,10 +15,18 @@
<affiliation>
<jobtitle>Web Beans (JSR-299 Reference Implementation) lead
</jobtitle>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</author>
<author>
+ <firstname>Dan</firstname>
+ <surname>Allen</surname>
+ <affiliation>
+ <jobtitle>Senior Software Engineer</jobtitle>
+ <orgname>Red Hat, Inc.</orgname>
+ </affiliation>
+ </author>
+ <author>
<firstname>David</firstname>
<surname>Allen</surname>
</author>
@@ -32,7 +40,7 @@
<surname>Guerrero</surname>
<contrib>Spanish Translation</contrib>
<affiliation>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</othercredit>
<othercredit>
@@ -40,7 +48,7 @@
<surname>Ki,</surname>
<contrib>Korean Translation</contrib>
<affiliation>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</othercredit>
<othercredit>
@@ -48,7 +56,7 @@
<surname>Chuang</surname>
<contrib>Traditional Chinese Translation</contrib>
<affiliation>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</othercredit>
<othercredit>
Modified: doc/trunk/reference/en-US/Book_Info.xml
===================================================================
--- doc/trunk/reference/en-US/Book_Info.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/Book_Info.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,8 +1,13 @@
-<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
+<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<bookinfo>
- <title>Web Beans: Java Contexts and Dependency Injection</title>
- <subtitle>The new standard for dependency injection and contextual state management</subtitle>
+ <title>Weld - JSR-299 Reference Implementation</title>
+ <subtitle>
+ JSR-299: The new Java standard for dependency injection and contextual life cycle management
+ </subtitle>
- <xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
</bookinfo>
Modified: doc/trunk/reference/en-US/environments.xml
===================================================================
--- doc/trunk/reference/en-US/environments.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/environments.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -272,7 +272,7 @@
</listitem>
</itemizedlist>
- <section>
+ <section id="weld-se">
<title>Web Beans SE Module</title>
<para>To make life easy for developers Web Beans provides a special module with a
Modified: doc/trunk/reference/en-US/example.xml
===================================================================
--- doc/trunk/reference/en-US/example.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/example.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,16 +1,15 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="example">
- <title>JSF web application example</title>
+ <title>JSF web application example</title>
- <para>Let's illustrate these ideas with a full example. We're going
- to implement user login/logout for an application that uses JSF. First,
- we'll define a Web Bean to hold the username and password entered during
- login:</para>
+ <para>
+ Let's illustrate these ideas with a full example. We're going to implement a user login/logout for an application
+ that uses JSF. First, we'll define a request-scoped bean to hold the username and password entered during login:
+ </para>
<programlisting role="JAVA"><![CDATA[@Named @RequestScoped
public class Credentials {
-
private String username;
private String password;
@@ -19,86 +18,110 @@
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
-
}]]></programlisting>
- <para>This Web Bean is bound to the login prompt in the following JSF form:</para>
+ <para>This bean is bound to the login prompt in the following JSF form:</para>
-<programlisting role="JAVA"><![CDATA[<h:form>
- <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
- <h:outputLabel for="username">Username:</h:outputLabel>
- <h:inputText id="username" value="#{credentials.username}"/>
- <h:outputLabel for="password">Password:</h:outputLabel>
- <h:inputText id="password" value="#{credentials.password}"/>
- </h:panelGrid>
- <h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
- <h:commandButton value="Logout" acion="#{login.logout}" rendered="#{login.loggedIn}"/>
+ <programlisting role="JAVA"><![CDATA[<h:form>
+ <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
+ <h:outputLabel for="username">Username:</h:outputLabel>
+ <h:inputText id="username" value="#{credentials.username}"/>
+ <h:outputLabel for="password">Password:</h:outputLabel>
+ <h:inputText id="password" value="#{credentials.password}"/>
+ </h:panelGrid>
+ <h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
+ <h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form>]]></programlisting>
- <para>The actual work is done by a session scoped Web Bean that maintains
- information about the currently logged-in user and exposes the <literal>User</literal>
- entity to other Web Beans:</para>
+ <para>
+ The actual work is done by a session-scoped bean that maintains information about the currently logged-in user
+ and exposes the <literal>User</literal> entity to other beans:
+ </para>
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Named
+ <programlisting role="JAVA"><![CDATA[@SessionScoped @Named
public class Login {
- @Current Credentials credentials;
- @PersistenceContext EntityManager userDatabase;
+ @Inject Credentials credentials;
+ @Inject @UserDatabase EntityManager userDatabase;
- private User user;
+ private User user;
- public void login() {
-
- List<User> results = userDatabase.createQuery(
- "select u from User u where u.username=:username and u.password=:password")
- .setParameter("username", credentials.getUsername())
- .setParameter("password", credentials.getPassword())
- .getResultList();
+ public void login() {
+ List<User> results = userDatabase.createQuery(
+ "select u from User u where u.username = :username and u.password = :password")
+ .setParameter("username", credentials.getUsername())
+ .setParameter("password", credentials.getPassword())
+ .getResultList();
- if ( !results.isEmpty() ) {
- user = results.get(0);
- }
-
- }
+ if (!results.isEmpty()) {
+ user = results.get(0);
+ }
+ else {
+ // perhaps add code here to report a failed login
+ }
+ }
- public void logout() {
- user = null;
- }
+ public void logout() {
+ user = null;
+ }
- public boolean isLoggedIn() {
- return user!=null;
- }
+ public boolean isLoggedIn() {
+ return user != null;
+ }
- @Produces @LoggedIn User getCurrentUser() {
- return user;
- }
+ @Produces @LoggedIn User getCurrentUser() {
+ return user;
+ }
}]]></programlisting>
- <para>Of course, <literal>@LoggedIn</literal> is a binding annotation:</para>
+ <para><literal>@LoggedIn</literal> and <literal>@UserDatabase</literal> are custom qualifier annotations:</para>
-<programlisting role="JAVA"><![CDATA[@Retention(RUNTIME)
-@Target({TYPE, METHOD, FIELD})
-@BindingType
+ <programlisting role="JAVA"><![CDATA[@Retention(RUNTIME)
+@Target({TYPE, METHOD, PARAMETER, FIELD})
+@Documented
+@Qualifier
public @interface LoggedIn {}]]></programlisting>
- <para>Now, any other Web Bean can easily inject the current user:</para>
+ <programlisting role="JAVA"><![CDATA[@Retention(RUNTIME)
+@Target({METHOD, PARAMETER, FIELD})
+@Documented
+@Qualifier
+public @interface UserDatabase {}]]></programlisting>
-<programlisting role="JAVA"><![CDATA[public class DocumentEditor {
+ <para>
+ We need an adapter bean to expose our typesafe <literal>EntityManager</literal>:
+ </para>
- @Current Document document;
- @LoggedIn User currentUser;
- @PersistenceContext EntityManager docDatabase;
+ <programlisting role="JAVA"><![CDATA[public class UserDatabaseProducer {
+ @Produces @UserDatabase @PersistenceContext EntityManager userDatabase;
+}]]></programlisting>
+
+ <para>Now, any other bean can easily inject the current user, as well as other beans:</para>
+
+ <programlisting role="JAVA"><![CDATA[public class DocumentEditor {
+ @Inject Document document;
+ @Inject @LoggedIn User currentUser;
+ @Inject @DocumentDatabase EntityManager docDatabase;
- public void save() {
- document.setCreatedBy(currentUser);
- docDatabase.persist(document);
- }
-
+ public void save() {
+ document.setCreatedBy(currentUser);
+ docDatabase.persist(document);
+ }
}]]></programlisting>
- <para>Hopefully, this example gives a flavor of the Web Bean programming model.
- In the next chapter, we'll explore Web Beans dependency injection in greater
- depth.</para>
+ <para>Or we can reference the current user in a JSF view:</para>
-</chapter>
\ No newline at end of file
+ <programlisting role="XML"><![CDATA[<h:panelGroup rendered="#{login.loggedIn}">
+ signed in as #{currentUser.username}
+</h:panelGroup>]]></programlisting>
+
+ <para>
+ Hopefully, this example gives a flavor of the CDI services. In the next chapter, we'll explore examples from the
+ CDI reference implementation, Weld, in greater depth.
+ </para>
+
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</chapter>
Modified: doc/trunk/reference/en-US/gettingstarted.xml
===================================================================
--- doc/trunk/reference/en-US/gettingstarted.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/gettingstarted.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,293 +1,617 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<chapter id="gettingstarted">
+<!-- TODO
+Explain use of war:inplace to use jetty
+Java SE numberguess example
+-->
-<chapter id="ri">
- <title>Getting started with Web Beans, the Reference Implementation of JSR-299</title>
+ <title>Getting started Weld, the JSR-299 reference implementation</title>
<para>
- The Web Beans is being developed at
- <ulink url="http://seamframework.org/WebBeans">the Seam project</ulink>.
- You can download the latest developer release of Web Beans from the
- <ulink url="http://seamframework.org/Download">the downloads page</ulink>.
- </para>
+ Weld, the JSR-299 RI (Reference Implementation), is being developed as part of the <ulink
+ url="http://seamframework.org/Weld">Seam project</ulink>. You can download the latest community release of Weld
+ from the <ulink url="http://seamframework.org/Download">download page</ulink>. Information about the Weld source
+ code repository and instructions about how to obtain and build the source can be found on the same page.
+ </para>
- <para>
- Web Beans comes with a two deployable example applications:
- <literal>webbeans-numberguess</literal>, a war example which runs on
- JBoss AS, Tomcat, Jetty and Google App Engine, containing only
- simple beans, and <literal>webbeans-translator</literal> an ear example,
- containing enterprise beans.
- To run the examples you'll need the following:
+ <para>
+ Weld comes with two starter example applications, in addition to more specialized examples. The first,
+ <literal>weld-numberguess</literal>, is a web (WAR) example containing only non-transactional managed beans.
+ This example can be run on a wide range of servers, including JBoss AS, GlassFish, Apache Tomcat, Jetty, Google
+ App Engine, and any compliant Java EE 6 container. The second example, <literal>weld-translator</literal>, is
+ an enterprise (EAR) example that contains session beans. This example must be run on JBoss AS 5.2 or any compliant
+ Java EE 6 container.
</para>
- <itemizedlist>
- <listitem>
- <para>the latest release of Web Beans,</para>
- </listitem>
- <listitem>
- <para>JBoss AS 5.2.0, or</para>
- </listitem>
- <listitem>
- <para>Jetty 6.1.x, or</para>
- </listitem>
- <listitem>
- <para>Apache Tomcat 6.0.x, and</para>
- </listitem>
- <listitem>
- <para>Ant 1.7.0.</para>
- </listitem>
- </itemizedlist>
+ <para>
+ Both examples use JSF 2.0 as the web framework and, as such, can be found in the examples/jsf directory of the
+ Weld distribution.
+ </para>
+
+ <section id="prerequisites">
+ <title>Prerequisites</title>
+
+ <para>
+ To run the examples with the provided build scripts, you'll need the following:
+ </para>
- <section>
- <title>Using JBoss AS 5</title>
+ <itemizedlist>
+ <listitem>
+ <para>the latest release of Weld, which contains the examples</para>
+ </listitem>
+ <listitem>
+ <para>Ant 1.7.0, to build and deploy the examples</para>
+ </listitem>
+ <listitem>
+ <para>a supported runtime environment (minimum versions shown)</para>
+ <itemizedlist>
+ <listitem>
+ <para>JBoss AS 5.2.0 (currenly only nightly builds of JBoss AS 5.2.0.Beta1 are available), or</para>
+ </listitem>
+ <listitem>
+ <para>GlassFish 3.0, or</para>
+ </listitem>
+ <listitem>
+ <para>Apache Tomcat 6.0.x (WAR example only), or</para>
+ </listitem>
+ <listitem>
+ <para>Jetty 6.1.x (WAR example only)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>(optionally) Maven 2.x, to run the examples in an embedded servlet container</para>
+ </listitem>
+ </itemizedlist>
- <para>
- You'll need to download JBoss AS 5.2.0 from
- <ulink url="http://www.jboss.org/jbossas/downloads/">jboss.org</ulink>,
- and unzip it. For example:
+ <note>
+ <para>
+ You'll need a full install of Ant 1.7.0. Some linux distributions only supply a partial installation of Ant
+ which cause the build to fail. If you encounter problems, verify that ant-nodeps.jar is on the classpath.
+ </para>
+ </note>
+
+ <para>
+ In the next few sections, you'll be using the Ant command (ant) to invoke the Ant build script in each of the two
+ examples to compile, assemble and deploy the example to JBoss AS and, for the WAR example, Apache Tomcat. You can
+ also deploy the generated artifact (WAR or EAR) to any other container that supports Java EE 6, such as GlassFish V3.
</para>
+
+ <para>
+ If you have Maven installed, you can also use the Maven command (mvn) to compile and assemble the standalone
+ artifact (WAR or EAR) and, for the WAR example, run it in an embedded container.
+ </para>
- <programlisting><![CDATA[$ cd /Applications
-$ unzip ~/jboss-5.2.0.Beta.zip]]></programlisting>
+ <para>The sections below cover the steps for deploying with both Ant and Maven in detail. Let's start with JBoss AS.</para>
+ </section>
+
+ <section id="jbossas">
+ <title>Deploying to JBoss AS</title>
+
+ <para>
+ To deploy the examples to JBoss AS, you'll need <ulink src="http://jboss.org/jbossas/">JBoss AS
+ 5.2.0.Beta1</ulink> or above. If a release of the JBoss AS 5.2 line isn't yet available, you can download a
+ <ulink src="http://hudson.jboss.org/hudson/view/JBoss%20AS/job/JBoss-AS-5.x-sun16/">nightly snapshot</ulink>.
+ The reason JBoss AS 5.2.0.Beta1 or above is required is because it's the first release that has both CDI and
+ Bean Validation support built-in, making it close enough to Java EE 6 to run the examples. The good news is
+ that there are no additional modifications you have to make to the server. It's ready to go!
+ </para>
+
+ <para>
+ After you have downloaded JBoss AS, extract it. (We recommended renaming the folder to include the
+ <literal>as</literal> qualifier so it's clear that it's the application server). You can move the extracted
+ folder anywhere you like. Whereever it lays to rest, that's what we'll call the JBoss AS installation
+ directory, or <literal>JBOSS_HOME</literal>.
+ </para>
+
+ <programlisting><![CDATA[$> unzip jboss-5.2.*.zip
+$> mv jboss-5.2.*/ jboss-as-5.2]]></programlisting>
+
+ <para>
+ In order for the build scripts to know where to deploy the example, you have to tell them where to find your
+ JBoss AS installation (i.e., <literal>JBOSS_HOME</literal>). Create a new file named local.build.properties in
+ the examples directory of the Weld distribution and assign the path of your JBoss AS installation to the property
+ key <literal>jboss.home</literal>, as follows:
+ </para>
+
+ <programlisting><![CDATA[jboss.home=/path/to/jboss-as-5.2]]></programlisting>
+
+ <para>
+ You're now ready to deploy your first example!
+ </para>
+
+ <para>
+ Switch to the examples/jsf/numberguess directory and execute the Ant deploy target:
+ </para>
+
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess
+$> ant deploy]]></programlisting>
+
+ <para>
+ If you haven't already, start JBoss AS. You can either start JBoss AS from a Linux shell:
+ </para>
+
+ <programlisting><![CDATA[$> cd /path/to/jboss-as-5.2
+$> ./bin/run.sh]]></programlisting>
+
+ <para>
+ a Windows command window:
+ </para>
+
+ <programlisting><![CDATA[$> cd c:\path\to\jboss-as-5.2\bin
+$> run]]></programlisting>
+
+ <para>
+ or you can start the server using an IDE, like Eclipse.
+ </para>
+
<note>
<para>
- JBoss AS 5.2.0 comes with Web Beans built in.
+ If you are using Eclipse, you should seriously consider installing the <ulink
+ src="http://www.jboss.org/tools">JBoss Tools</ulink> add-ons, which include a wide variety of tooling for
+ JSR-299 and Java EE development, as well as an enhanced JBoss AS server view.
</para>
</note>
-
+
<para>
- Now, you're ready to deploy your first example!
+ Wait a few seconds for the application to deploy (or the application server to start) and see if you can
+ determine the most efficient approach to pinpoint the random number at the local URL <ulink
+ src="http://localhost:8080/weld-numberguess">http://localhost:8080/weld-numberguess</ulink>.
</para>
-
+
<tip>
<para>
- The build scripts for the examples offer a number of targets for
- JBoss AS, these are:
+ The Ant build script includes additional targets for JBoss AS to deploy and undeploy the archive in either exploded or packaged format and to tidy things up.
</para>
<itemizedlist>
<listitem>
<para>
- <literal>ant restart</literal> - deploy the example in exploded
- format
+ <literal>ant restart</literal> - deploy the example in exploded format to JBoss AS
</para>
</listitem>
<listitem>
<para>
- <literal>ant explode</literal> - update an exploded example, without
- restarting the deployment
+ <literal>ant explode</literal> - update an exploded example, without restarting the deployment
</para>
</listitem>
<listitem>
<para>
- <literal>ant deploy</literal> - deploy the example in compressed jar format
+ <literal>ant deploy</literal> - deploy the example in compressed jar format to JBoss AS
</para>
</listitem>
<listitem>
<para>
- <literal>ant undeploy</literal> - remove the example from the server
+ <literal>ant undeploy</literal> - remove the example from JBoss AS
</para>
</listitem>
<listitem>
<para>
<literal>ant clean</literal> - clean the example
- </para>
+ </para>
</listitem>
</itemizedlist>
</tip>
-
+
<para>
- To deploy the numberguess example:
+ The second starter example, <literal>weld-translator</literal>, will translate your text into Latin. (Well,
+ not really, but the stub is there for you to implement, at least. Good luck!) To try it out, switch to the
+ translator example directory and execute the deploy target:
</para>
- <programlisting>$ cd examples/jsf/numberguess
-ant deploy</programlisting>
+ <programlisting><![CDATA[$> cd examples/jsf/translator
+$> ant deploy]]></programlisting>
+ <note>
+ <para>
+ The translator uses session beans, which are packaged in an EJB module within an EAR. Java EE 6 will allow
+ session beans to be deployed in WAR modules, but that's a topic for future chapter.
+ </para>
+ </note>
+
<para>
- Start JBoss AS:
+ Again, wait a few seconds for the application to deploy (if you are bored, read the log messages), and visit
+ <ulink src="http://localhost:8080/weld-translator">http://localhost:8080/weld-translator</ulink> to begin
+ pseudo-translating.
</para>
-
- <programlisting>$ /Application/jboss-5.2.0.Beta/bin/run.sh</programlisting>
-
- <tip>
- <para>
- If you use Windows, use the <literal>run.bat</literal>script.
- </para>
- </tip>
+
+ <para>
+ TODO Insert note about upgrading the Weld deployer that directs reader to section on the JBoss AS environment
+ </para>
+ </section>
+
+ <section id="glassfish">
+ <title>Deploying to GlassFish</title>
+
<para>
- Wait for the application to deploy, and enjoy hours of fun at
- <ulink url="http://localhost:8080/webbeans-numberguess" />!
+ Deploying to GlassFish should be easy, right? After all, it's the Java EE 6 reference implementation. Since
+ it's the Java EE 6 reference implementation, that means it also bundles the JSR-299 reference implementation,
+ Weld! So yes, it's very easy.
</para>
-
+
<para>
- Web Beans includes a second simple example that will translate your text
- into Latin. The numberguess example is a war example, and uses only simple
- beans; the translator example is an ear example, and includes enterprise
- beans, packaged in an EJB module. To try it out:
+ To deploy the examples to GlassFish, you'll need the final <ulink
+ src="https://glassfish.dev.java.net/">GlassFish V3</ulink> release (the preview release won't do). If the final
+ release isn't yet available, you can download a <ulink
+ src="http://download.java.net/glassfish/v3/promoted/">promoted build</ulink> in the meantime. Select the b69
+ preview release or above that ends in either -unix.sh or -windows.exe depending on your platform. After the
+ download is complete, execute the installer. On Linux/Unix, you'll need to first make the script executable.
</para>
+
+ <programlisting><![CDATA[$> chmod 755 glassfish-v3-b69-unix.sh
+$> ./glassfish-v3-b69-unix.sh]]></programlisting>
+
+ <para>
+ On Windows you can just click on the executable. Follow the instructions in the installer. It will create a
+ single domain named <literal>domain1</literal>. You'll use that domain to deploy the example. We recommend that
+ you choose 7070 as the main HTTP port to avoid conflicts with a running instance of JBoss AS (or Apache
+ Tomcat).
+ </para>
- <programlisting>$ cd examples/translator
-ant deploy</programlisting>
-
<para>
- Wait for the application to deploy, and visit
- <ulink url="http://localhost:8080/webbeans-translator" />!
+ If you've deployed either of the starter examples, <literal>weld-numberguess</literal> or
+ <literal>weld-translator</literal>, to JBoss AS, then you already have the deployable artifact you need.
+ If not, switch to either of the two directories and build it.
</para>
-
+
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess (or examples/jsf/translator)
+$> ant package]]></programlisting>
+
+ <para>
+ The deployable archive for the <literal>weld-numberguess</literal>, named weld-numberguess.war, ends up in the
+ example's target directory. The archive for the <literal>weld-translator</literal> example, named
+ weld-translator.ear, ends up in the example's ear/target directory. All you need to do now is deploy them to
+ GlassFish.
+ </para>
+
+ <para>
+ You deploy applications to GlassFish using the <ulink src="http://localhost:4848">GlassFish Admin
+ Console</ulink>. To get the Admin Console running, you need to start a GlassFish domain, in our case
+ <literal>domain1</literal>. Switch to the bin folder in the directory where you installed GlassFish and execute
+ the following command:
+ </para>
+
+ <programlisting><![CDATA[$> asadmin start-domain domain1]]></programlisting>
+
+ <para>
+ After a few seconds you can visit the Admin Console in the browser at the URL <ulink
+ src="http://localhost:4848">http://localhost:4848</ulink>. In the tree on the left-hand
+ side of the page, click on "Applications", then click on the "Deploy..." button under
+ the heading "Applications" and select the deployable artifact for either of the two examples.
+ The deployer should recognize that you have selected a Java EE artifact and allow you to
+ start it. You can see the examples running at either <ulink
+ src="http://localhost:7070/weld-numberguess">http://localhost:7070/weld-numberguess</ulink> or <ulink
+ src="http://localhost:7070/weld-translator">http://localhost:7070/weld-translator</ulink>,
+ depending on which example you deployed.
+ </para>
+
+ <para>
+ The reason the same artifact can be deployed to both JBoss AS and GlassFish, without any modifications, is
+ because all of the features being used are part of the standard platform. And what a capable platform it has
+ become!
+ </para>
+
</section>
- <section>
- <title>Using Apache Tomcat 6.0</title>
-
- <para>
- You'll need to download Tomcat 6.0.18 or later from
- <ulink url="http://tomcat.apache.org/download-60.cgi">tomcat.apache.org</ulink>,
- and unzip it. For example:
+ <section id="tomcat">
+ <title>Deploying to Apache Tomcat</title>
+
+ <para>
+ Technically, CDI doesn't support servlet containers. That's because the contexts and dependency injection
+ services are provided by the Java EE container, not the Servlet API. However, CDI implementations can choose to
+ support servlet containers through an extension. Weld does this.</para>
+
+ <para>
+ Weld ships with a Servlet listener which bootstraps the CDI environment, registers the BeanManager in JNDI and
+ provides injection into servlets. Basically, it emulates the work done by the Java EE container. The only
+ limitation is that you cannot use enterprise features such as session beans and container-managed transactions.
</para>
-
- <programlisting><![CDATA[$ cd /Applications
-$ unzip ~/apache-tomcat-6.0.18.zip]]></programlisting>
<para>
- Next, download Web Beans from
- <ulink url="http://seamframework.org/Download">seamframework.org</ulink>,
- and unzip it. For example
+ Let's give the Weld servlet extension a spin on Apache Tomcat. First, you'll need to download Tomcat 6.0.18 or later
+ from <ulink src="http://tomcat.apache.org/download-60.cgi">tomcat.apache.org</ulink> and extract it.
</para>
+
+ <programlisting><![CDATA[$> unzip apache-tomcat-6.0.18.zip]]></programlisting>
+
+ <para>
+ You have two choices for how you can deploy the application to Tomcat. You can deploy it by pushing the
+ artifact to the hot deploy directory using Ant or you can deploy to the server across HTTP using a Maven
+ plugin. The Ant approach doesn't require that you have Maven installed, so we'll start there. If you want to
+ use Maven, you can just skip ahead.
+ </para>
+
+ <section id="tomcat-ant">
+ <title>Deploying with Ant</title>
+
+ <para>
+ In order for Ant to push the artifact to the Tomcat hot deploy directory, it needs to know where the Tomcat
+ installation is located. Again, we need to setup a propery in the local.build.properties file in the
+ examples directory of the Weld distribution. If you haven't yet created this file, do so now. Then assign
+ the path of your Tomcat installation to the property key tomcat.home.
+ </para>
+
+ <programlisting><![CDATA[tomcat.home=/path/to/apache-tomcat-6]]></programlisting>
+
+ <para>
+ Now you're ready to deploy the numberguess example to Tomcat!
+ </para>
+
+ <para>
+ Change to the examples/jsf/numberguess directory again and run the Ant deploy target for Tomcat:
+ </para>
+
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess
+$> ant tomcat.deploy]]></programlisting>
+
+ <tip>
+ <para>
+ The Ant build script includes additional targets for Tomcat to deploy and undeploy the archive in either
+ exploded or packaged format. They are the same target names used for JBoss AS, prefixed with "tomcat.".
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>ant tomcat.restart</literal> - deploy the example in exploded format to Tomcat
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.explode</literal> - update an exploded example, without restarting the deployment
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.deploy</literal> - deploy the example in compressed jar format to Tomcat
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.undeploy</literal> - remove the example from Tomcat
+ </para>
+ </listitem>
+ </itemizedlist>
+ </tip>
+
+ <para>
+ If you haven't already, start Tomcat. You can either start Tomcat from a Linux shell:
+ </para>
+
+ <programlisting><![CDATA[$> cd /path/to/apache-tomcat-6
+$> ./bin/start.sh]]></programlisting>
+
+ <para>
+ a Windows command window:
+ </para>
+
+ <programlisting><![CDATA[$> cd c:\path\to\apache-tomcat-6\bin
+$> start]]></programlisting>
+
+ <para>
+ or you can start the server using an IDE, like Eclipse.
+ </para>
+
+ <para>
+ Wait a few seconds for the application to deploy (or the application server to start) and see if you can figure
+ out the most efficient approach to pinpoint the random number at the local URL
+ <ulink src="http://localhost:8080/weld-numberguess">http://localhost:8080/weld-numberguess</ulink>!
+ </para>
+
+ </section>
- <programlisting><![CDATA[$ cd ~/
-$ unzip ~/webbeans-$VERSION.zip]]></programlisting>
-
- <programlisting>tomcat.home=/Applications/apache-tomcat-6.0.18</programlisting>
+ <section id="tomcat-maven">
+ <title>Deploying with Maven</title>
- <tip>
<para>
- The build scripts for the examples offer a number of targets for
- Tomcat, these are:
+ You can also deploy the application to Tomcat using Maven. This section is a bit more advanced, so skip it
+ unless you are itching to use Maven natively. Of course, you'll first need to make sure that you have Maven
+ installed on your path, similar to how you setup Ant.
</para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>mvn war:inplace tomcat:run -Ptomcat</literal> - deploy the example in an embedded Tomcat
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>mvn compile war:exploded tomcat:exploded -Ptomcat</literal> - deploy the example to a running Tomcat install
- </para>
- </listitem>
- </itemizedlist>
+
<para>
- See the <code>jsf/numberguess/readme.txt</code> for more details.
+ The Maven plugin communicates with Tomcat over HTTP, so it doesn't care where you have installed Tomcat.
+ However, the plugin configuration assumes you are running Tomcat in its default configuration, with a hostname
+ of localhost and port 8080. The readme.txt file in the example directory has information about how to modify
+ the Maven settings to accomodate a different setup.
</para>
- </tip>
-
+
+ <para>
+ To allow Maven to communicate with Tomcat over HTTP, edit the conf/tomcat-users.xml file in your Tomcat
+ installation and add the following line:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<user username="admin" password="" roles="manager"/>]]></programlisting>
+
+ <para>
+ Restart Tomcat. You can now deploy the application to Tomcat with Maven using this command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn compile war:exploded tomcat:exploded -Ptomcat]]></programlisting>
+
+ <para>
+ Once the application is deployed, you can redeploy it using this command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn tomcat:redeploy -Ptomcat]]></programlisting>
+
+ <para>
+ The <literal>-Ptomcat</literal> argument activates the tomcat profile defined in the Maven POM (pom.xml).
+ Among other things, this profile activates the Tomcat plugin.
+ </para>
+
+ <para>
+ Rather than shipping the container off to a standalone Tomcat installation, you can also execute the
+ application in an embedded Tomcat 6 container:
+ </para>
+
+ <programlisting><![CDATA[$> mvn war:inplace tomcat:run -Ptomcat]]></programlisting>
+
+ <para>
+ The advantage of using the embedded server is that changes to assets in src/main/webapp take affect
+ immediately. If a change to a webapp configuration file is made, the application may automatically redeploy
+ (depending on the plugin configuration). If you make a change to a classpath resource, you need to execute a
+ build:
+ </para>
+
+ <programlisting><![CDATA[$> mvn compile war:inplace -Ptomcat]]></programlisting>
+
+ <para>
+ There are several other Maven goals that you can use if you are hacking on the example, which are documented in
+ the example's readme.txt file.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="jetty">
+ <title>Deploying to Jetty</title>
+
+ <!-- subsections? -->
+
<para>
- To deploy the numberguess example for tomcat:
+ Support for Jetty in the examples is a more recent addition. Since Jetty is traditionally used with Maven,
+ there are no Ant targets. You must invoke the Maven build directly to deploy the examples to Jetty out of the
+ box. Also, only the <literal>weld-numberguess</literal> example is configured for Jetty support at the time of
+ this writing.
</para>
-
- <programlisting>$ cd examples/jsf/numberguess
-ant tomcat.deploy</programlisting>
<para>
- Edit <code>$TOMCAT_HOME/conf/tomcat-users.xml</code> and add
+ If you've read through the entire Tomcat section, then you're all ready to go. The Maven build parallels the
+ embedded Tomcat deployment. If not, don't worry. We'll still go over everything in this section that you need
+ to know.
</para>
-
- <programlisting><![CDATA[<user username="admin" password="" roles="manager"/>]]></programlisting>
-
- <para>This allows Maven to communicate with Tomcat.</para>
-
+
<para>
- Start Tomcat:
+ The Maven POM (pom.xml) includes a profile named jetty that activates the Maven Jetty plugin, which you can use
+ to start Jetty in embedded mode and deploy the application in place. You don't need anything else installed
+ except to have the Maven command (mvn) on your path. The rest will be downloaded from the internet when the
+ build is run.
</para>
-
- <programlisting>$ /Applications/apache-tomcat-6.0.18/bin/startup.sh</programlisting>
-
- <tip>
- <para>
- If you use Windows, use the <literal>startup.bat</literal>script.
- </para>
- </tip>
-
- <para>Deploy the application</para>
-
- <programlisting>$ mvn compile war:exploded tomcat:exploded -Ptomcat</programlisting>
-
+
<para>
- Wait for the application to deploy, and enjoy hours of fun at
- <ulink url="http://localhost:8080/webbeans-numberguess" />!
+ To run the <literal>weld-numberguess</literal> example on Jetty, switch to the example directory and execute
+ the inplace goal of the Maven WAR plugin followed by the run goal of the Maven Jetty plugin with the jetty
+ profile enabled, as follows:
</para>
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess
+$> mvn war:inplace jetty:run -Pjetty]]></programlisting>
+
+ <para>
+ The log output of Jetty will be shown in the console. Once Jetty reports that the application has deployed, you
+ can access it at the following local URL: <ulink
+ src="http://localhost:9090/weld-numberguess">http://localhost:9090/weld-numberguess</ulink>. The port is
+ defined in the Maven Jetty plugin configuration within the jetty profile.
+ </para>
+
+ <para>
+ Any changes to assets in src/main/webapp take affect immediately. If a change to a webapp configuration file is
+ made, the application may automatically redeploy. The redeploy behavior can be fined tuned in the plugin
+ configuration. If you make a change to a classpath resource, you need to execute a build and the inplace goal
+ of the Maven WAR plugin, again with the jetty profile enabled.
+ </para>
+
+ <programlisting><![CDATA[$> mvn compile war:inplace -Pjetty]]></programlisting>
+
+ <para>
+ The war:inplace goal copies the compiled classes and JARs inside src/main/webapp, under WEB-INF/classes and
+ WEB-INF/lib, respectively, mixing source and compiled files. However, the build does work around these
+ temporary files by excluding them from the packaged WAR and cleaning them during the Maven clean phase.
+ </para>
+
+ <para>
+ You have two options if you want to run the example on Jetty from the IDE. You can either install the
+ m2eclispe[link] plugin and run the goals as described above. Your other option is to start the Jetty container
+ from a Java application.
+ </para>
+
+ <para>
+ First, initialize the Eclipse project:
+ </para>
+
+ <programlisting><![CDATA[$> mvn clean eclipse:clean eclipse:eclipse -Pjetty-ide]]></programlisting>
+
+ <para>
+ Next, assemble all the necessary resources under src/main/webapp:
+ </para>
+
+ <programlisting><![CDATA[$> mvn war:inplace -Pjetty-ide]]></programlisting>
+
+ <para>
+ Now, you are ready to run the server in Eclipse. Import the project into your Eclipse workspace using "Import
+ Existing Project into Workspace. Then, find the start class in src/jetty/java and run its main method as a Java
+ Application. Jetty will launch. You can view the application at the following local URL: <ulink
+ src="http://localhost:8080">http://localhost:8080</ulink>. Pay particular attention to the port in the URL and
+ the lack of a trailing context path.
+ </para>
+
+ <!-- NOTE Transition paragraph into the example explanation sections. -->
+ <para>
+ Now that you have gotten the starter applications deployed on the server of your choice, you probably want to
+ know a little bit about how they actually work. It's time to pull the covers back and dive into the internals
+ of these two examples. Let's start with the simpler of the two examples, <literal>weld-numberguess</literal>.
+ </para>
+
</section>
- <section>
- <title>Using GlassFish</title>
+ <section id="numberguess">
+ <title>The numberguess example in depth</title>
- <para>TODO</para>
- </section>
-
- <section>
- <title>The numberguess example</title>
-
<para>
- In the numberguess application you get given 10 attempts to guess a
- number between 1 and 100. After each attempt, you will be told whether
- you are too high, or too low.
+ In the numberguess application you get given 10 attempts to guess a number between 1 and 100. After each
+ attempt, you will be told whether you are too high or too low.
</para>
<para>
- The numberguess example is comprised of a number of Web Beans,
- configuration files, and Facelet JSF pages, packaged as a war. Let's
- start with the configuration files.
+ The numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views,
+ packaged as a WAR module. Let's start by examining the configuration files.
</para>
<para>
- All the configuration files for this example are located in
- <literal>WEB-INF/</literal>, which is stored in
- <literal>WebContent</literal> in the source tree. First, we have
- <literal>faces-config.xml</literal>, in which we tell JSF to use
- Facelets:
+ All the configuration files for this example are located in <literal>WEB-INF/</literal>, which can be found in
+ the <literal>src/main/webapp</literal> directory of the example. First, we have the JSF 2.0 version of
+ <literal>faces-config.xml</literal>. A standardized version of Facelets is the default view handler in JSF
+ 2.0, so there's really nothing that we have to configure. Thus, the configuration consists of only the root
+ element.
</para>
- <programlisting role="XML"><![CDATA[<?xml version='1.0' encoding='UTF-8'?>
-<faces-config version="1.2"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
-
- <application>
- <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
- </application>
-
+ <programlisting role="XML"><![CDATA[<faces-config version="2.0"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
</faces-config>]]></programlisting>
<para>
- There is an empty <literal>web-beans.xml</literal> file, which marks
- this application as a Web Beans application.
+ There's also an empty <literal>beans.xml</literal> file, which tells the container to look for beans in this
+ application and to activate the CDI services.
</para>
<para>
- Finally there is <literal>web.xml</literal>:
+ Finally, there's the familiar <literal>web.xml</literal>:
</para>
<programlistingco>
<areaspec>
- <area id="faces.servlet" coords="12" />
- <area id="faces.servlet.mapping" coords="18" />
- <area id="faces.default.suffix" coords="23" />
- <area id="session.timeout" coords="28" />
- <area id="webbeans.listener" coords="32" />
+ <area id="faces.servlet" coords="10" />
+ <area id="faces.servlet.mapping" coords="16" />
+ <area id="faces.default.suffix" coords="21" />
+ <area id="session.timeout" coords="26" />
</areaspec>
- <programlisting><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
-
-<web-app version="2.5"
- xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <programlisting role="XML"><![CDATA[<web-app version="2.5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <display-name>Web Beans Numbergues example</display-name>
+ <display-name>weld-jsf-numberguess-war</display-name>
+ <description>Weld JSF numberguess example (WAR)</description>
- <!-- JSF -->
-
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
@@ -312,18 +636,18 @@
<calloutlist>
<callout arearefs="faces.servlet">
<para>
- Enable and load the JSF servlet
+ Enable and initialize the JSF servlet
</para>
</callout>
<callout arearefs="faces.servlet.mapping">
<para>
- Configure requests to <literal>.jsf</literal> pages to be
+ Configure requests for URLs ending in <literal>.jsf</literal> to be
handled by JSF
</para>
</callout>
<callout arearefs="faces.default.suffix">
<para>
- Tell JSF that we will be giving our source files (facelets) an
+ Tell JSF that we will be giving our JSF views (Facelets templates) an
extension of <literal>.xhtml</literal>
</para>
</callout>
@@ -337,76 +661,71 @@
<note>
<para>
- Whilst this demo is a JSF demo, you can use Web Beans with any
- Servlet based web framework.
+ This demo uses JSF 2 as the view framework, but you can use Weld with any Servlet-based web framework, such
+ as JSF 1.2 or Wicket.
</para>
</note>
<para>
- Let's take a look at the Facelet view:
+ Let's take a look at the main JSF view, src/main/webapp/home.xhtml.
</para>
<programlistingco>
<areaspec>
<area id="template" coords="8" />
- <area id="messages2" coords="12" />
- <area id="instructions" coords="19" />
- <area id="guess" coords="25" />
- <area id="validator" coords="30" />
- <area id="submit" coords="33" />
+ <area id="statusMessages" coords="12" />
+ <area id="instructions" coords="20" />
+ <area id="guess" coords="27" />
+ <area id="validator" coords="29" />
+ <area id="submit" coords="30" />
</areaspec>
- <programlisting><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <programlisting role="HTML"><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:ui="http://java.sun.com/jsf/facelets"
- xmlns:h="http://java.sun.com/jsf/html"
- xmlns:f="http://java.sun.com/jsf/core"
- xmlns:s="http://jboss.com/products/seam/taglib">
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core">
- <ui:composition template="template.xhtml">
- <ui:define name="content">
- <h1>Guess a number...</h1>
- <h:form id="NumberGuessMain">
- <div style="color: red">
- <h:messages id="messages" globalOnly="false"/>
- <h:outputText id="Higher" value="Higher!" rendered="#{game.number gt game.guess and game.guess ne 0}"/>
- <h:outputText id="Lower" value="Lower!" rendered="#{game.number lt game.guess and game.guess ne 0}"/>
- </div>
-
- <div>
- I'm thinking of a number between #{game.smallest} and #{game.biggest}.
- You have #{game.remainingGuesses} guesses.
- </div>
-
- <div>
- Your guess:
- <h:inputText id="inputGuess"
- value="#{game.guess}"
- required="true"
- size="3"
- disabled="#{game.number eq game.guess}">
- <f:validateLongRange maximum="#{game.biggest}"
- minimum="#{game.smallest}"/>
- </h:inputText>
- <h:commandButton id="GuessButton"
- value="Guess"
- action="#{game.check}"
- disabled="#{game.number eq game.guess}"/>
- </div>
- <div>
- <h:commandButton id="RestartButton" value="Reset" action="#{game.reset}" immediate="true" />
- </div>
- </h:form>
- </ui:define>
- </ui:composition>
+ <ui:composition template="/template.xhtml">
+ <ui:define name="content">
+ <h1>Guess a number...</h1>
+ <h:form id="numberGuess">
+ <div style="color: red">
+ <h:messages id="messages" globalOnly="false"/>
+ <h:outputText id="Higher" value="Higher!"
+ rendered="#{game.number gt game.guess and game.guess ne 0}"/>
+ <h:outputText id="Lower" value="Lower!"
+ rendered="#{game.number lt game.guess and game.guess ne 0}"/>
+ </div>
+
+ <div>
+ I'm thinking of a number between #{game.smallest} and #{game.biggest}.
+ You have #{game.remainingGuesses} guesses remaining.
+ </div>
+
+ <div>
+ Your guess:
+ <h:inputText id="inputGuess" value="#{game.guess}"
+ size="3" required="true" disabled="#{game.number eq game.guess}"
+ validator="#{game.validateNumberRange}"/>
+ <h:commandButton id="guessButton" value="Guess"
+ action="#{game.check}" disabled="#{game.number eq game.guess}"/>
+ </div>
+ <div>
+ <h:commandButton id="restartButton" value="Reset" action="#{game.reset}" immediate="true"/>
+ </div>
+ </h:form>
+ </ui:define>
+ </ui:composition>
</html>]]></programlisting>
<calloutlist>
<callout arearefs="template">
<para>
- Facelets is a templating language for JSF, here we are
- wrapping our page in a template which defines the header.
+ Facelets is the built-in templating language for JSF. Here we are
+ wrapping our page in a template which defines the layout.
</para>
</callout>
- <callout arearefs="messages2">
+ <callout arearefs="statusMessages">
<para>
There are a number of messages which can be sent to the user,
"Higher!", "Lower!" and "Correct!"
@@ -415,73 +734,69 @@
<callout arearefs="instructions">
<para>
As the user guesses, the range of numbers they can guess gets
- smaller - this sentance changes to make sure they know what
- range to guess in.
+ smaller - this sentance changes to make sure they know the
+ number range of a valid guess.
</para>
</callout>
<callout arearefs="guess">
<para>
- This input field is bound to a Web Bean, using the value
+ This input field is bound to a bean property using a value
expression.
</para>
</callout>
<callout arearefs="validator">
<para>
- A range validator is used to make sure the user doesn't
+ A validator binding is used to make sure the user doesn't
accidentally input a number outside of the range in which they
can guess - if the validator wasn't here, the user might use
- up a guess on an out of range number.
+ up a guess on an out of bounds number.
</para>
</callout>
<callout arearefs="submit">
<para>
And, of course, there must be a way for the user to send their
- guess to the server. Here we bind to an action method on the
- Web Bean.
+ guess to the server. Here we bind to an action method on the bean.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
- The example exists of 4 classes, the first two of which are binding
- types. First, there is the <literal>@Random</literal> binding type,
- used for injecting a random number:
+ The example exists of 4 classes, the first two of which are qualifiers. First, there is the
+ <literal>@Random</literal> qualifier, used for injecting a random number:
</para>
<programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
-@BindingType
+@Qualifier
public @interface Random {}]]></programlisting>
<para>
- There is also the <literal>@MaxNumber</literal> binding type, used for
+ There is also the <literal>@MaxNumber</literal> qualifier, used for
injecting the maximum number that can be injected:
</para>
<programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
-@BindingType
+@Qualifier
public @interface MaxNumber {}
]]></programlisting>
<para>
- The <literal>Generator</literal> class is responsible for creating the
- random number, via a producer method. It also exposes the maximum
- possible number via a producer method:
+ The application-scoped <literal>Generator</literal> class is responsible for creating the random number, via a
+ producer method. It also exposes the maximum possible number via a producer method:
</para>
<programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Generator {
+public class Generator implements Serializable {
+
+ private java.util.Random random = new java.util.Random(System.currentTimeMillis());
- private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
-
private int maxNumber = 100;
- java.util.Random getRandom()
- {
+ java.util.Random getRandom() {
return random;
}
@@ -489,117 +804,65 @@
return getRandom().nextInt(maxNumber);
}
- @Produces @MaxNumber int getMaxNumber()
- {
+ @Produces @MaxNumber int getMaxNumber() {
return maxNumber;
}
}]]></programlisting>
<para>
- You'll notice that the <literal>Generator</literal> is application
- scoped; therefore we don't get a different random each time.
+ The <literal>Generator</literal> is application scoped, so we don't get a different random each time.
</para>
+
+ <note>
+ <para>
+ The package declaration and imports have been excluded from these listings. The complete listing is
+ available in the example source code.
+ </para>
+ </note>
<para>
- The final Web Bean in the application is the session scoped
- <literal>Game</literal>.
+ The final bean in the application is the session-scoped <literal>Game</literal> class. This is the primary
+ entry point of the application. It's responsible for setting up or resetting the game, capturing and validating
+ the user's guess and providing feedback to the user with a <literal>FacesMessage</literal>. We've used
+ constructor injection to initialize the game with a random number.
</para>
-
+
<para>
- You'll note that we've used the <literal>@Named</literal>
- annotation, so that we can use the bean through EL in the JSF page.
- Finally, we've used constructor injection to initialize the game with
- a random number. And of course, we need to tell the player when they've
- won, so we give feedback with a <literal>FacesMessage</literal>.
+ You'll notice that we've also added the <literal>@Named</literal> annotation to this class. This annotation is
+ only required when you want to make the bean accessible to a JSF view via EL (i.e., #{game}).
</para>
-
- <programlisting role="JAVA"><![CDATA[package org.jboss.webbeans.examples.numberguess;
+
+ <programlisting role="JAVA"><![CDATA[@Named
+@SessionScoped
+public class Game implements Serializable {
-import java.io.Serializable;
-
-import javax.annotation.PostConstruct;
-import javax.enterprise.context.SessionScoped;
-import javax.enterprise.inject.Instance;
-import javax.faces.application.FacesMessage;
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIInput;
-import javax.faces.context.FacesContext;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-@Named
-@SessionScoped
-public class Game implements Serializable
-{
private int number;
-
private int guess;
private int smallest;
-
- @Inject @MaxNumber
- private int maxNumber;
-
private int biggest;
private int remainingGuesses;
-
+
+ @Inject @MaxNumber private int maxNumber;
@Inject @Random Instance<Integer> randomNumber;
- public Game()
- {
- }
-
- public int getNumber()
- {
- return number;
- }
+ public Game() {}
- public int getGuess()
- {
- return guess;
- }
-
- public void setGuess(int guess)
- {
- this.guess = guess;
- }
-
- public int getSmallest()
- {
- return smallest;
- }
-
- public int getBiggest()
- {
- return biggest;
- }
-
- public int getRemainingGuesses()
- {
- return remainingGuesses;
- }
-
- public String check()
- {
- if (guess>number)
- {
+ public void check() {
+ if (guess > number) {
biggest = guess - 1;
}
- if (guess<number)
- {
+ else if (guess < number) {
smallest = guess + 1;
}
- if (guess == number)
- {
+ else if (guess == number) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
}
remainingGuesses--;
- return null;
}
@PostConstruct
- public void reset()
- {
+ public void reset() {
this.smallest = 0;
this.guess = 0;
this.remainingGuesses = 10;
@@ -607,108 +870,164 @@
this.number = randomNumber.get();
}
- public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value)
- {
- if (remainingGuesses <= 0)
- {
+ public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value) {
+ if (remainingGuesses <= 0) {
FacesMessage message = new FacesMessage("No guesses left!");
context.addMessage(toValidate.getClientId(context), message);
- ((UIInput)toValidate).setValid(false);
+ ((UIInput) toValidate).setValid(false);
return;
}
int input = (Integer) value;
- if (input < smallest || input > biggest)
- {
- ((UIInput)toValidate).setValid(false);
+ if (input < smallest || input > biggest) {
+ ((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid guess");
context.addMessage(toValidate.getClientId(context), message);
}
}
-}
-]]></programlisting>
- <section>
- <title>The numberguess example in Tomcat</title>
+ public int getNumber() {
+ return number;
+ }
+
+ public int getGuess() {
+ return guess;
+ }
+
+ public void setGuess(int guess) {
+ this.guess = guess;
+ }
+
+ public int getSmallest() {
+ return smallest;
+ }
+
+ public int getBiggest() {
+ return biggest;
+ }
+
+ public int getRemainingGuesses() {
+ return remainingGuesses;
+ }
+
+}]]></programlisting>
+
+ <section id="numberguess-servlet">
+ <title>The numberguess example in Apache Tomcat or Jetty</title>
<para>
- The numberguess for Tomcat differs in a couple of ways. Firstly,
- Web Beans should be deployed as a Web Application library in
- <literal>WEB-INF/lib</literal>. For your convenience we provide a
- single jar suitable for running Web Beans in any servlet container
- <literal>webbeans-servlet.jar</literal>.
+ A couple of modifications must be made to the numberguess artifact in order to deploy it to Tomcat or Jetty.
+ First, Weld must be deployed as a Web Application library under <literal>WEB-INF/lib</literal> since the
+ servlet container does not provide the CDI services. For your convenience we provide a single JAR suitable
+ for running Weld in any servlet container (including Jetty), <literal>weld-servlet.jar</literal>.
</para>
<tip>
<para>
- Of course, you must also include JSF and EL, as well common
- annotations (<literal>jsr250-api.jar</literal>) which a JEE server
- includes by default.
+ You must also include the JARs for JSF, EL, and the common annotations
+ (<literal>jsr250-api.jar</literal>), all of which are provided by the Java EE platorm (a Java EE
+ application server). Are you starting to appreciate why a Java EE platform is worth using?
</para>
</tip>
<para>
- Secondly, we need to explicitly specify the servlet listener
- (used to boot Web Beans, and control it's interaction with requests)
- in <literal>web.xml</literal>:
+ Second, we need to explicitly specify the servlet listener in <literal>web.xml</literal>, again because the
+ container isn't doing this stuff for you. The servlet listener boots Weld and controls it's interaction with
+ requests.
</para>
- <programlisting><![CDATA[<listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+ <programlisting role="XML"><![CDATA[<listener>
+ <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>]]></programlisting>
-
+
+ <para>
+ When Weld boots, it places the <literal>javax.enterprise.inject.spi.BeanManager</literal>, the portable SPI
+ for obtaining bean instances, in the ServletContext under a variable name equal to the fully-qualified
+ interface name. You generally don't need to access this interface, but Weld makes use of it.
+ </para>
+
</section>
- <section id="numberguessWicket">
- <title>The numberguess example for Apache Wicket</title>
+ <section id="numberguess-wicket">
+ <title>The numberguess example for Apache Wicket</title>
<para>
- Whilst JSR-299 specifies integration with Java ServerFaces, Web
- Beans allows you to inject into Wicket components, and also allows
- you to use a conversation context with Wicket. In this section,
- we'll walk you through the Wicket version of the numberguess
- example.
+ Weld includes a number of portable extensions for JSR-299, including an extension for Wicket, which allows
+ you to inject beans into Wicket components and leverage the conversation context. In this section, we'll
+ walk you through the Wicket version of the numberguess example.
</para>
- <note>
+ <tip>
<para>
- You may want to review the Wicket documentation at
- <ulink url="http://wicket.apache.org/">http://wicket.apache.org/</ulink>.
+ You may want to review the Wicket documentation at <ulink
+ url="http://wicket.apache.org/">http://wicket.apache.org/</ulink> before reading this section, if you
+ aren't already familiar with the framework.
</para>
- </note>
+ </tip>
<para>
- Like the previous example, the Wicket WebBeans examples make use of
- the <literal>webbeans-servlet</literal> module. The use of the
- <ulink url="http://jetty.mortbay.org/">Jetty servlet container</ulink>
- is common in the Wicket community, and is chosen here as the
- runtime container in order to facilitate comparison between the
- standard Wicket examples and these examples, and also to show how
- the webbeans-servlet integration is not dependent upon Tomcat as the
- servlet container.
+ Wicket is another environment that relies on the Weld servlet extension. The use of <ulink
+ url="http://jetty.mortbay.org">Jetty</ulink> is common in the Wicket community, and is thus chosen here as
+ the runtime container. You've seen already that Jetty is perfectly capable of running CDI applications with
+ Weld add-ons, and this environment is no different.
</para>
- <para>
- These examples make use of the Eclipse IDE; instructions are also
- given to deploy the application from the command line.
- </para>
+ <note>
+ <para>
+ We'll also be using the Eclipse IDE in these examples. Instructions are provided later for running the
+ example from the commandline, but since you'll likely need to do more than just deploy examples, we'll get
+ setup in this full development environment.
+ </para>
+ </note>
<section>
<title>Creating the Eclipse project</title>
<para>
- To generate an Eclipse project from the example:
+ To use the Wicket example in Eclipse, you have one of two choices. You can either use a Maven plugin to
+ generate a regular Eclipse Web project, or you can open the example natively using the <ulink
+ src="http://m2eclipse.sonatype.org/">m2eclipse plugin</ulink>. Since the Weld source code relies so
+ heavily on Maven, we encourage you to bite the bullet and adopt the m2eclipse plugin. Both approaches are
+ described here for your convenience..
</para>
+
+ <para>
+ If you have m2eclipse installed, you can open any Maven project directly. From within Eclipse, select
+ <emphasis>File -> Import... -> Maven Projects</emphasis>. Then, browse to the location of the Wicket
+ numberguess example. You should see that Eclipse recognizes the existance of a Maven project.
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/m2eclipse-wicket-numberguess-import.png" format="PNG"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ This will create a project in your workspace called <literal>weld-wicket-numberguess</literal>.
+ </para>
+
+ <para>
+ You'll notice after importing, the project has a build error. That's because we need to enable a Maven
+ profile. Right-click on the project and select <emphasis>Properties</emphasis>, then select the
+ <emphasis>Maven</emphasis> tab in the window that appears. In the form field labeled "Active Maven
+ Profiles (comma separated):", type <literal>jetty</literal>. That will enable some extra dependencies
+ that allow the project to compile. You're now ready to develop!
+ </para>
+
+ <para>
+ If you are not using the m2eclipse plugin, you have to follow different steps to import the project.
+ First, switch into the Wicket numberguess example, then execute the Maven Eclipse plugin with the jetty
+ profile activated, as follows:
+ </para>
- <programlisting><![CDATA[cd examples/wicket/numberguess
+ <programlisting><![CDATA[$> cd examples/wicket/numberguess
mvn -Pjetty eclipse:eclipse]]></programlisting>
<para>
- Then, from eclipse, choose <emphasis>File -> Import -> General -> Existing Projects into Workspace</emphasis>,
- select the root directory of the numberguess example, and click
- finish. Note that if you do not intend to run the example with jetty from
- within eclipse, omit the "-Pjetty." This will create a project in your
- workspace called <literal>webbeans-wicket-numberguess</literal>
+ Then, from Eclipse, choose <emphasis>File -> Import... -> General -> Existing Projects into
+ Workspace</emphasis>, select the root directory of the numberguess example, and click Finish. This will
+ create a project in your workspace called <literal>weld-wicket-numberguess</literal>.
</para>
<mediaobject>
@@ -716,22 +1035,23 @@
<imagedata fileref="images/wicket-numberguess-project.png" format="PNG"/>
</imageobject>
</mediaobject>
+
+ <para>
+ It's time to get the example running!
+ </para>
+
</section>
<section>
<title>Running the example from Eclipse</title>
<para>
- This project follows the <literal>wicket-quickstart</literal>
- approach of creating an instance of Jetty in the
- <literal>Start</literal> class. So running the example is as
- simple as right-clicking on that Start class in
- <literal>src/test/java</literal> in the
- <emphasis>Package Explorer</emphasis> and choosing
- <emphasis>Run as Java Application</emphasis>. You should
- see console output related to Jetty starting up; then visit able
- <literal>http://localhost:8080</literal> to view the app. To
- debug choose <emphasis>Debug as Java Application</emphasis>.
+ This project follows the <literal>wicket-quickstart</literal> approach of creating an instance of Jetty
+ in the <literal>Start</literal> class. So running the example is as simple as right-clicking on that
+ Start class in <literal>src/test/java</literal> in the <emphasis>Package Explorer</emphasis> and choosing
+ <emphasis>Run as Java Application</emphasis>. You should see console output related to Jetty starting up;
+ then visit able <literal>http://localhost:8080</literal> to view the app. To debug choose <emphasis>Debug
+ as Java Application</emphasis> instead.
</para>
</section>
@@ -739,144 +1059,179 @@
<title>Running the example from the command line in JBoss AS or Tomcat</title>
<para>
- This example can also be deployed from the command line in a
- (similar to the other examples). Assuming you have set up the
- <literal>build.properties</literal> file in the
- <literal>examples</literal> directory to specify the location of
- JBoss AS or Tomcat, as previously described, you can run
- <literal>ant deploy</literal> from the
- <literal>examples/wicket/numberguess</literal> directory, and
- access the application at
- <literal>http://localhost:8080/webbeans-numberguess-wicket</literal>.
+ This example can also be deployed from the command line in a (similar to the other examples). Assuming
+ you have set up the <literal>local.build.properties</literal> file in the <literal>examples</literal>
+ directory to specify the location of JBoss AS or Tomcat, as previously described, you can run:
</para>
+
+ <programlisting><![CDATA[$> ant deploy]]></programlisting>
+
+ <para>to deploy the example to JBoss AS, and:</para>
+
+ <programlisting><![CDATA[$> ant tomcat.deploy]]></programlisting>
+
+ <para>
+ to deploy the example to Tomcat. You can then access application at
+ <literal>http://localhost:8080/weld-numberguess-wicket</literal>.
+ </para>
+
+ <para>
+ Alternatively, you can run the application in place on an embedded Jetty container using the following
+ Maven command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn jetty:run -Pjetty]]></programlisting>
+
+ <para>
+ Enough toying with deployment, let's dive into the code.
+ </para>
+
</section>
<section>
<title>Understanding the code</title>
<para>
- JSF uses Unified EL expressions to bind view layer components in
- JSP or Facelet views to beans, Wicket defines it's components in
- Java. The markup is plain html with a one-to-one mapping between
- html elements and the view components. All view logic, including
- binding of components to models and controlling the response of
- view actions, is handled in Java. The integration of Web Beans
- with Wicket takes advantage of the same binding annotations used
- in your business layer to provide injection into your WebPage
- subclass (or into other custom wicket component subclasses).
+ The code in the wicket numberguess example is very similar to the JSF-based numberguess example. The
+ business layer is identical! Where things differ is in view binding. JSF uses Unified EL expressions to
+ bind XML-based view layer components in JSF views to beans. In contrast, Wicket defines its components in
+ Java. These Java-based view components have a one-to-one mapping with HTML elements in an adjacent (pure)
+ HTML file. All view logic, including binding of components to models and controlling the response of view
+ actions, is handled in Java.
</para>
-
+
<para>
- The code in the wicket numberguess example is very similar to the
- JSF-based numberguess example. The business layer is identical!
+ The integration of Weld with Wicket takes advantage of the same qualifier annotations used in your
+ business layer to provide injection into your <literal>WebPage</literal> subclass (or into other custom
+ Wicket component subclasses).
</para>
-
+
<para>
- Differences are:
+ Here's where things differ from the JSF numberguess example:
</para>
+
<itemizedlist>
<listitem>
<para>
- Each wicket application must have a
- <literal>WebApplication</literal> subclass, In our case,
- our application class is
- <literal>SampleApplication</literal>:
+ Each wicket application must have a <literal>WeldApplication</literal> subclass. In our case, our
+ application class is <literal>NumberGuessApplication</literal>:
</para>
- <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication {
- @Override
- public Class getHomePage() {
+ <programlisting role="JAVA"><![CDATA[public class NumberGuessApplication extends WeldApplication {
+ @Override public Class getHomePage() {
return HomePage.class;
}
}]]></programlisting>
<para>
- This class specifies which page wicket should treat as our
- home page, in our case, <literal>HomePage.class</literal>
+ This class specifies which page Wicket should treat as our home page, in our case,
+ <literal>HomePage.class</literal>
</para>
</listitem>
<listitem>
<para>
- In <literal>HomePage</literal> we see typical wicket code
- to set up page elements. The bit that is interesting is
- the injection of the <literal>Game</literal> bean:
+ In <literal>HomePage</literal>, we see typical Wicket code to set up page elements. The bit that is
+ interesting is the injection of the <literal>Game</literal> bean:
</para>
- <programlisting><![CDATA[ @Current Game game;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject Game game;]]></programlisting>
<para>
- The <literal>Game</literal> bean is can then be used, for
- example, by the code for submitting a guess:
+ The <literal>Game</literal> bean is can then be used, for example, by the code for submitting a
+ guess:
</para>
- <programlisting><![CDATA[final Component guessButton = new AjaxButton("GuessButton") {
+ <programlisting role="JAVA"><![CDATA[final Component guessButton = new AjaxButton("GuessButton") {
protected void onSubmit(AjaxRequestTarget target, Form form) {
- if (game.check()) {]]></programlisting>
+ if (game.check()) {
+ info("Correct!");
+ setVisible(false);
+ prompt.setVisible(false);
+ guessLabel.setVisible(false);
+ inputGuess.setVisible(false);
+ }
+ else if (game.getRemainingGuesses() == 0) {
+ info("Sorry, the answer was " + game.getNumber());
+ setVisible(false);
+ guessLabel.setVisible(false);
+ inputGuess.setVisible(false);
+ }
+ else if (game.getNumber() > game.getGuess()) {
+ info("Higher!");
+ }
+ else if (game.getNumber() < game.getGuess()) {
+ info("Lower");
+ }
+ target.addComponent(form);
+ }
+}; ]]></programlisting>
<note>
<para>
- All injections may be serialized; actual storage of the
- bean is managed by JSR-299. Note that Wicket
- components, like the HomePage and it subcomponents, are
+ All injections may be serialized; actual storage of the bean is managed by JSR-299. Note that
+ Wicket components, like the <literal>HomePage</literal> and it subcomponents, are
<emphasis>not</emphasis> JSR-299 beans.
</para>
<para>
- Wicket components allow injection, but they
- <emphasis>cannot</emphasis> use interceptors, decorators
- and lifecycle callbacks such as
- <literal>@PostConstruct</literal> or
- <literal>@Initializer</literal> methods.
+ Wicket components allow injection, but they <emphasis>cannot</emphasis> use interceptors,
+ decorators and lifecycle callbacks such as <literal>@PostConstruct</literal> or
+ <literal>@Initializer</literal> methods. The components would need to delegate to actual beans
+ to leverage these features.
</para>
</note>
</listitem>
<listitem>
<para>
- The example uses AJAX for processing of button events, and
- dynamically hides buttons that are no longer relevant, for
- example when the user has won the game.
+ The example uses AJAX for processing of button events, and dynamically hides buttons that are no
+ longer relevant, for example when the user has won the game.
</para>
</listitem>
<listitem>
<para>
- In order to activate wicket for this webapp, the Wicket
- filter is added to web.xml, and our application class is
- specified:
+ In order to activate Wicket for this webapp, the Wicket filter is added to web.xml, and our
+ application class is specified in web.xml:
</para>
- <programlisting><![CDATA[<filter>
- <filter-name>wicket.numberguess-example</filter-name>
+
+ <programlisting role="XML"><![CDATA[<filter>
+ <filter-name>Wicket Filter</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
- <param-value>org.jboss.webbeans.examples.wicket.SampleApplication</param-value>
+ <param-value>org.jboss.weld.examples.wicket.NumberGuessApplication</param-value>
</init-param>
</filter>
<filter-mapping>
- <filter-name>wicket.numberguess-example</filter-name>
+ <filter-name>Wicket Filter</filter-name>
<url-pattern>/*</url-pattern>
-</filter-mapping>
-
-<listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
-</listener>]]></programlisting>
+</filter-mapping>]]></programlisting>
+
<para>
- Note that the servlet listener is also added, as in the
- Tomcat example, in order to boostrap Web Beans when Jetty
- starts, and to hook Web Beans into the Jetty servlet
- request and session lifecycles.
+ The servlet listener is still required, as in the Tomcat example, to bootstrap CDI when Jetty
+ starts and to hook CDI into the Jetty servlet request and session life cycles. However, rather than
+ putting it into the web.xml, it is placed into an override file,
+ src/main/webapp/WEB-INF/jetty-additions-to-web.xml, that is passed to Jetty as extra descriptor to
+ be appended to the web.xml configuration.
</para>
+
+ <programlisting role="XML"><![CDATA[<web-app version="2.4" ...>
+ <listener>
+ <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
+ </listener>
+</web-app>]]></programlisting>
+
</listitem>
</itemizedlist>
</section>
</section>
- <section>
+ <section id="numberguess-se">
<title>The numberguess example for Java SE with Swing</title>
<para>
This example can be found in the
- <literal>examples/se/numberguess</literal> folder of the Web
- Beans distribution.
+ <literal>examples/se/numberguess</literal> folder of the Weld
+ distribution.
</para>
@@ -906,7 +1261,7 @@
<para>
execute the following command
</para>
- <programlisting>mvn -Drun</programlisting>
+ <programlisting>$> mvn -Drun</programlisting>
</listitem>
</itemizedlist>
@@ -915,7 +1270,7 @@
<para>
There is an empty <literal>beans.xml</literal> file in the root
package (<literal>src/main/resources/beans.xml</literal>), which
- marks this application as a Web Beans application.
+ marks this application as a CDI application.
</para>
<para>
@@ -933,57 +1288,46 @@
<area id="reset" coords="68" />
</areaspec>
<programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Game implements Serializable
-{
+public class Game implements Serializable {
private int number;
private int guess;
private int smallest;
-
- @MaxNumber
- private int maxNumber;
-
private int biggest;
private int remainingGuesses;
private boolean validNumberRange = true;
- @Current Generator rndGenerator;
+ @Inject @MaxNumber private int maxNumber;
+ @Inject Generator rndGenerator;
+
...
- public boolean isValidNumberRange()
- {
+ public boolean isValidNumberRange() {
return validNumberRange;
}
- public boolean isGameWon()
- {
+ public boolean isGameWon() {
return guess == number;
}
- public boolean isGameLost()
- {
+ public boolean isGameLost() {
return guess != number && remainingGuesses <= 0;
}
- public boolean check()
- {
+ public boolean check() {
boolean result = false;
- if ( checkNewNumberRangeIsValid() )
- {
- if ( guess > number )
- {
+ if (checkNewNumberRangeIsValid()) {
+ if (guess > number) {
biggest = guess - 1;
}
- if ( guess < number )
- {
+ if (guess < number) {
smallest = guess + 1;
}
- if ( guess == number )
- {
+ if (guess == number) {
result = true;
}
@@ -993,14 +1337,12 @@
return result;
}
- private boolean checkNewNumberRangeIsValid()
- {
- return validNumberRange = ( ( guess >= smallest ) && ( guess <= biggest ) );
+ private boolean checkNewNumberRangeIsValid() {
+ return validNumberRange = ((guess >= smallest) && (guess <= biggest));
}
@PostConstruct
- public void reset()
- {
+ public void reset() {
this.smallest = 0;
...
this.number = rndGenerator.next();
@@ -1084,12 +1426,10 @@
<area id="challenge" coords="5" />
<area id="result" coords="16" />
</areaspec>
- <programlisting role="JAVA"><![CDATA[public class MessageGenerator
-{
- @Current Game game;
+ <programlisting role="JAVA"><![CDATA[public class MessageGenerator {
+ @Inject Game game;
- public String getChallengeMessage()
- {
+ public String getChallengeMessage() {
StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a number between " );
challengeMsg.append( game.getSmallest() );
challengeMsg.append( " and " );
@@ -1099,35 +1439,33 @@
return challengeMsg.toString();
}
- public String getResultMessage()
- {
- if ( game.isGameWon() )
- {
+ public String getResultMessage() {
+ if ( game.isGameWon() ) {
return "You guess it! The number was " + game.getNumber();
- } else if ( game.isGameLost() )
- {
+ }
+ else if ( game.isGameLost() ) {
return "You are fail! The number was " + game.getNumber();
- } else if ( ! game.isValidNumberRange() )
- {
+ }
+ else if ( ! game.isValidNumberRange() ) {
return "Invalid number range!";
- } else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
- {
+ }
+ else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES ) {
return "What is your first guess?";
- } else
- {
+ }
+ else {
String direction = null;
- if ( game.getGuess() < game.getNumber() )
- {
+ if ( game.getGuess() < game.getNumber() ) {
direction = "Higher";
- } else
- {
+ }
+ else {
direction = "Lower";
}
return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
}
}
+
}]]></programlisting>
<calloutlist>
<callout arearefs="game">
@@ -1166,13 +1504,12 @@
<area id="replay" coords="44" />
<area id="refresh" coords="50" />
</areaspec>
- <programlisting role="JAVA"><![CDATA[public class NumberGuessFrame extends javax.swing.JFrame
-{
- private @Current Game game;
- private @Current MessageGenerator msgGenerator;
+ <programlisting role="JAVA"><![CDATA[public class NumberGuessFrame extends javax.swing.JFrame {
- public void start( @Observes @Deployed Manager manager )
- {
+ private @Inject Game game;
+ private @Inject MessageGenerator msgGenerator;
+
+ public void start( @Observes @Deployed Manager manager ) {
java.awt.EventQueue.invokeLater( new Runnable()
{
public void run()
@@ -1199,8 +1536,7 @@
...
}
- private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
- {
+ private void guessButtonActionPerformed( java.awt.event.ActionEvent evt ) {
int guess = Integer.parseInt(guessText.getText());
game.setGuess( guess );
@@ -1209,14 +1545,12 @@
}
- private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
- {
+ private void replayBtnActionPerformed( java.awt.event.ActionEvent evt ) {
game.reset();
refreshUI();
}
- private void refreshUI()
- {
+ private void refreshUI() {
mainLabel.setText( msgGenerator.getChallengeMessage() );
messageLabel.setText( msgGenerator.getResultMessage() );
guessText.setText( "" );
@@ -1243,7 +1577,7 @@
</callout>
<callout arearefs="start">
<para>
- This application is started in the usual Web Beans SE way,
+ This application is started in the usual CDI SE way,
by observing the <literal>@Deployed Manager</literal> event.
</para>
</callout>
@@ -1309,30 +1643,29 @@
</section>
</section>
- <section>
- <title>The translator example</title>
+ <section id="translator">
+ <title>The translator example in depth</title>
<para>
- The translator example will take any sentences you enter, and translate
- them to Latin.
+ The translator example will take any sentences you enter, and translate them to Latin. (Well, not really, but
+ the stub is there for you to implement, at least. Good luck!)
</para>
<para>
- The translator example is built as an ear, and contains EJBs. As a result, it's structure is more complex than
+ The translator example is built as an EAR and contains EJBs. As a result, it's structure is more complex than
the numberguess example.
</para>
<note>
<para>
- EJB 3.1 and Jave EE 6 allow you to package EJBs in a war, which will
- make this structure much simpler!
+ Jave EE 6, which bundles EJB 3.1, allows you to package EJBs in a WAR, which will make this structure much
+ simpler! Still, there are other advantages of using an EAR.
</para>
</note>
<para>
- First, let's take a look at the ear aggregator, which is located in
- <literal>webbeans-translator-ear</literal> module. Maven automatically
- generates the <literal>application.xml</literal> for us:
+ First, let's take a look at the EAR aggregator, which is located in the example's <literal>ear</literal> directory. Maven
+ automatically generates the <literal>application.xml</literal> for us from this plugin configuration:
</para>
<programlisting role="XML"><![CDATA[<plugin>
@@ -1341,62 +1674,62 @@
<configuration>
<modules>
<webModule>
- <groupId>org.jboss.webbeans.examples.translator</groupId>
- <artifactId>webbeans-translator-war</artifactId>
- <contextRoot>/webbeans-translator</contextRoot>
+ <groupId>org.jboss.weld.examples.jsf.translator</groupId>
+ <artifactId>weld-jsf-translator-war</artifactId>
+ <contextRoot>/weld-translator</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>]]></programlisting>
<para>
- Here we set the context path, which gives us a nice url
- (<ulink url="http://localhost:8080/webbeans-translator">http://localhost:8080/webbeans-translator</ulink>).
+ This configuration overrides the web context path, resulting in this application URL: <ulink
+ url="http://localhost:8080/weld-translator">http://localhost:8080/weld-translator</ulink>.
</para>
<tip>
<para>
- If you aren't using Maven to generate these files, you would need
+ If you weren't using Maven to generate these files, you would need
<literal>META-INF/application.xml</literal>:
</para>
- <programlisting role="XML"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
-<application xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd"
- version="5">
- <display-name>webbeans-translator-ear</display-name>
- <description>Ear Example for the reference implementation of JSR 299: Web Beans</description>
+ <programlisting role="XML"><![CDATA[<application version="5"
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/javaee
+ http://java.sun.com/xml/ns/javaee/application_5.xsd">
+
+ <display-name>weld-jsf-translator-ear</display-name>
+ <description>The Weld JSF translator example (EAR)</description>
<module>
<web>
- <web-uri>webbeans-translator.war</web-uri>
- <context-root>/webbeans-translator</context-root>
+ <web-uri>weld-translator.war</web-uri>
+ <context-root>/weld-translator</context-root>
</web>
</module>
<module>
- <ejb>webbeans-translator.jar</ejb>
+ <ejb>weld-translator.jar</ejb>
</module>
</application>]]></programlisting>
</tip>
<para>
- Next, lets look at the war. Just as in the numberguess example, we have
- a <literal>faces-config.xml</literal> (to enable Facelets) and a
- <literal>web.xml</literal> (to enable JSF) in
- <literal>WebContent/WEB-INF</literal>.
+ Next, lets look at the WAR, which is located in the example's <literal>war</literal> directory. Just as in the
+ numberguess example, we have a <literal>faces-config.xml</literal> for JSF 2.0 and a <literal>web.xml</literal>
+ (to activate JSF) under WEB-INF, both sourced from <literal>src/main/webapp/WEB-INF</literal>.
</para>
<para>
- More intersting is the facelet used to translate text. Just as in
- the numberguess example we have a template, which surrounds the form
- (ommitted here for brevity):
+ More intersting is the JSF view used to translate text. Just as in the numberguess example we have a template,
+ which surrounds the form (ommitted here for brevity):
</para>
- <programlisting role="XML"><![CDATA[<h:form id="NumberGuessMain">
-
+ <programlisting role="XML"><![CDATA[<h:form id="translator">
+
<table>
- <tr align="center" style="font-weight: bold" >
+ <tr align="center" style="font-weight: bold">
<td>
Your text
</td>
@@ -1406,10 +1739,10 @@
</tr>
<tr>
<td>
- <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
+ <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80"/>
</td>
<td>
- <h:outputText value="#{translator.translatedText}" />
+ <h:outputText value="#{translator.translatedText}"/>
</td>
</tr>
</table>
@@ -1420,93 +1753,128 @@
</h:form>]]></programlisting>
<para>
- The user can enter some text in the lefthand textarea, and hit the
- translate button to see the result to the right.
+ The user can enter some text in the left-hand textarea, and hit the translate button to see the result to the
+ right.
</para>
<para>
- Finally, let's look at the ejb module,
- <literal>webbeans-translator-ejb</literal>.
- In <literal>src/main/resources/META-INF</literal> there is just an
- empty <literal>web-beans.xml</literal>, used to mark the archive as
- containing Web Beans.
+ Finally, let's look at the EJB module, which is located in the example's <literal>ejb</literal> directory. In
+ <literal>src/main/resources/META-INF</literal> there is just an empty <literal>beans.xml</literal>, used to
+ mark the archive as containing beans.
</para>
<para>
- We've saved the most interesting bit to last, the code! The project has
- two simple beans, <literal>SentenceParser</literal> and
- <literal>TextTranslator</literal> and two enterprise beans,
- <literal>TranslatorControllerBean</literal> and
- <literal>SentenceTranslator</literal>. You should be getting quite
- familiar with what a Web Bean looks like by now, so we'll just
- highlight the most interesting bits here.
+ We've saved the most interesting bit to last, the code! The project has two simple beans,
+ <literal>SentenceParser</literal> and <literal>TextTranslator</literal> and two enterprise beans,
+ <literal>TranslatorControllerBean</literal> and <literal>SentenceTranslator</literal>. You should be getting
+ quite familiar with what a bean looks like by now, so we'll just highlight the most interesting bits here.
</para>
<para>
- Both <literal>SentenceParser</literal> and
- <literal>TextTranslator</literal> are dependent beans, and
- <literal>TextTranslator</literal> uses constructor initialization:
+ Both <literal>SentenceParser</literal> and <literal>TextTranslator</literal> are dependent beans, and
+ <literal>TextTranslator</literal> uses constructor injection:
</para>
- <programlisting role="JAVA"><![CDATA[public class TextTranslator {
+ <programlisting role="JAVA"><![CDATA[public class TextTranslator implements Serializable {
+
private SentenceParser sentenceParser;
- private Translator sentenceTranslator;
+
+ @EJB private Translator translator;
- @Initializer
- TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator)
- {
+ @Inject public TextTranslator(SentenceParser sentenceParser) {
this.sentenceParser = sentenceParser;
- this.sentenceTranslator = sentenceTranslator;]]></programlisting>
+ }
+
+ public String translate(String text) {
+ StringBuilder sb = new StringBuilder();
+ for (String sentence: sentenceParser.parse(text)) {
+ sb.append(translator.translate(sentence)).append(". ");
+ }
+ return sb.toString().trim();
+ }
+
+}]]></programlisting>
<para>
- <literal>TextTranslator</literal> is a stateless bean (with a local
- business interface), where the magic happens - of course, we couldn't
- develop a full translator, but we gave it a good go!
+ <literal>TextTranslator</literal> uses the simple bean (really just a plain Java class!)
+ <literal>SentenceParser</literal> to parse the sentence and then calls on the stateless bean with the local
+ business interface <literal>Translator</literal> to perform the translation. That's where the magic happens.
+ Of course, we couldn't develop a full translator, but it's convincing enough to anyone who doesn't understand
+ Latin!
</para>
-
+
+ <programlisting role="JAVA"><![CDATA[@Stateless
+public class SentenceTranslator implements Translator {
+
+ public String translate(String sentence) {
+ return "Lorem ipsum dolor sit amet";
+ }
+
+}]]></programlisting>
+
<para>
- Finally, there is UI orientated controller, that collects the text from
- the user, and dispatches it to the translator. This is a request
- scoped, named, stateful session bean, which injects the translator.
+ Finally, there is UI orientated controller. This is a request scoped, named, stateful session bean, which
+ injects the translator. It collects the text from the user and dispatches it to the translator. The bean also
+ has getters and setters for all the fields on the page.
</para>
<programlisting role="JAVA"><![CDATA[@Stateful
@RequestScoped
@Named("translator")
-public class TranslatorControllerBean implements TranslatorController
-{
+public class TranslatorControllerBean implements TranslatorController {
+
+ @Inject private TextTranslator translator;
- @Current TextTranslator translator;]]></programlisting>
+ private String inputText;
+ private String translatedText;
+
+ public void translate() {
+ translatedText = translator.translate(inputText);
+ }
+
+ public String getText() {
+ return inputText;
+ }
+
+ public void setText(String text) {
+ this.inputText = text;
+ }
+
+ public String getTranslatedText() {
+ return translatedText;
+ }
+
+ @Remove public void remove() {}
+
+}]]></programlisting>
+
<para>
- The bean also has getters and setters for all the fields on the page.
+ [CHECK is this still accurate?] Since this is a stateful session bean, we have to have a remove method. The
+ bean manager will call the remove method for you when the bean is destroyed; in this case at the end of the
+ request.
</para>
-
+
<para>
- As this is a stateful session bean, we have to have a remove method:
+ You'll notice in this example the smooth integration between the existing <literal>@EJB</literal> resource
+ injection annotation and the new <literal>@Inject</literal> annotation for injecting any managed or session
+ bean. The tight integration with Java EE is a key value proposition of CDI (not to mention a requirement).
</para>
-
- <programlisting role="JAVA"><![CDATA[ @Remove
- public void remove()
- {
-
- }]]></programlisting>
-
- <para>
- The Web Beans manager will call the remove method for you when the bean
- is destroyed; in this case at the end of the request.
- </para>
+
</section>
<para>
- That concludes our short tour of the Web Beans examples. For more on Web
- Beans , or to help out, please visit
- <ulink url="http://www.seamframework.org/WebBeans/Development">http://www.seamframework.org/WebBeans/Development</ulink>.
+ That concludes our short tour of the Weld starter examples. For more information on Weld, or to help out with
+ development, please visit <ulink
+ url="http://www.seamframework.org/Weld/Development">http://www.seamframework.org/Weld/Development</ulink>.
</para>
<para>
- We need help in all areas - bug fixing, writing new features, writing
- examples and translating this reference guide.
+ We need help in all areas - bug fixing, writing new features, writing examples and translating this reference
+ guide.
</para>
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
</chapter>
Added: doc/trunk/reference/en-US/images/m2eclipse-wicket-numberguess-import.png
===================================================================
(Binary files differ)
Property changes on: doc/trunk/reference/en-US/images/m2eclipse-wicket-numberguess-import.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/intro.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,538 +1,1000 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="intro">
- <title>Getting started with Web Beans</title>
+ <title>Getting started with JSR-299 (CDI)</title>
- <para>So you're already keen to get started writing your first Web Bean?
- Or perhaps you're skeptical, wondering what kinds of hoops the Web Beans
- specification will make you jump through! The good news is that you've
- probably already written and used hundreds, perhaps thousands of Web Beans.
- You might not even remember the first Web Bean you wrote.</para>
+ <para>
+ So you're keen to get started writing your first bean? Or perhaps you're skeptical, wondering what kinds of hoops
+ the CDI specification will make you jump through! The good news is that you've probably already written and used
+ hundreds, perhaps thousands of beans. CDI just helps you make use them in your web or enterprise application.
+ </para>
+
+ <section id="bean-definition">
+ <title>What is a bean?</title>
+
+ <para>
+ In this section, you'll learn that a bean is exactly what you think it is. Only now, it has a true identity in
+ Java EE.
+ </para>
+
+ <para>
+ Prior to Java EE 6, there existed no clear definition of a bean in the platform. Of course, we've been calling
+ Java classes used in web and enterprise applications beans for years. Third-party frameworks, such as Spring,
+ even have facilities for defining and creating beans; and there are a couple of bean variants in the platform
+ itself, including EJB session beans and JSF managed beans. What was missing was a common definition.
+ </para>
+
+ <para>
+ Java EE 6 finally lays down the definition of a bean in the Managed Bean specification. Managed Beans are
+ defined as container-managed objects with minimal requirements, otherwise known by their acronym, POJOs (Plain
+ Old Java Objects). They support a small set of basic services, such as resource injection, lifecycle callbacks
+ and interceptors. Companion specifications, such as EJB and CDI, build on this basic model. But, <emphasis>at
+ last</emphasis>, there is a universally accepted concept of a bean and a lightweight component model that's
+ aligned across the Java EE platform.
+ </para>
+
+ <para>
+ With certain, unique exceptions, every Java class that has a constructor with no parameters (or an alternate
+ constructor designated with the annotation <literal>@Inject</literal>) is a candidate for becoming a bean. Any
+ EJB session bean is also a candidate. They become beans, specifically CDI beans, if they reside in a Java EE
+ module that contains a special marker file (META-INF/beans.xml) and if instances of those classes are managed
+ by the Java EE container. Just know that, for simple JavaBean classes, there's no special metadata you need to
+ add to make them beans. They just are.
+ </para>
- <section>
- <title>Your first Web Bean</title>
+ <para>
+ The JavaBeans and EJBs you've been writing every day, up until now, have not been able to take advantage of the
+ new services defined by the CDI specification. But you'll be able to use every one of them with CDI --
+ allowing the container to create and destroy instances of your beans and associate them with a designed context
+ (or scope), injecting them into other beans, using them in EL expressions, specializing them with qualifier
+ annotations, even adding interceptors and decorators to them -- from this point forward without modifying
+ your code. At most, you'll have to add some annotations.
+ </para>
+
+ <para>
+ Let's see how to create your first bean.
+ </para>
+
+ </section>
+
+ <section id="first-bean">
+ <title>Your first bean (or is it?)</title>
+
+ <para>
+ Suppose that we have two existing Java classes, that we've been using for years in various applications. The
+ first class parses a string into a list of sentences:
+ </para>
- <para>With certain, very special exceptions, every Java class with a
- constructor that accepts no parameters is a Web Bean. That includes every
- JavaBean. Furthermore, every EJB 3-style session bean is a Web Bean. Sure,
- the JavaBeans and EJBs you've been writing every day have not been able to
- take advantage of the new services defined by the Web Beans specification,
- but you'll be able to use every one of them as Web Beans — injecting them
- into other Web Beans, configuring them via the Web Beans XML configuration
- facility, even adding interceptors and decorators to them — without
- touching your existing code.</para>
-
- <para>Suppose that we have two existing Java classes, that we've been using
- for years in various applications. The first class parses a string into a
- list of sentences:</para>
-
- <programlisting role="JAVA"><![CDATA[public class SentenceParser {
- public List<String> parse(String text) { ... }
+ <programlisting role="JAVA"><![CDATA[public class SentenceParser {
+ public List<String> parse(String text) { ... }
}]]></programlisting>
- <para>The second existing class is a stateless session bean front-end for an
- external system that is able to translate sentences from one language to
- another:</para>
+ <para>
+ The second existing class is a stateless session bean front-end for an external system that is able to
+ translate sentences from one language to another:
+ </para>
- <programlisting role="JAVA"><![CDATA[@Stateless
+ <programlisting role="JAVA"><![CDATA[@Stateless
public class SentenceTranslator implements Translator {
- public String translate(String sentence) { ... }
+ public String translate(String sentence) { ... }
}]]></programlisting>
- <para>Where <literal>Translator</literal> is the local interface:</para>
+ <para>Where <literal>Translator</literal> is the EJB local interface:</para>
- <programlisting role="JAVA"><![CDATA[@Local
+ <programlisting role="JAVA"><![CDATA[@Local
public interface Translator {
- public String translate(String sentence);
+ public String translate(String sentence);
}]]></programlisting>
- <para>Unfortunately, we don't have a preexisting class that translates whole
- text documents. So let's write a Web Bean that does this job:</para>
+ <para>
+ Unfortunately, we don't have a class that translates whole text documents. So let's write a bean for this job:
+ </para>
- <programlisting role="JAVA"><![CDATA[public class TextTranslator {
+ <programlisting role="JAVA"><![CDATA[public class TextTranslator {
+ private SentenceParser sentenceParser;
+ private Translator sentenceTranslator;
- private SentenceParser sentenceParser;
- private Translator sentenceTranslator;
+ @Inject
+ TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
+ this.sentenceParser = sentenceParser;
+ this.sentenceTranslator = sentenceTranslator;
+ }
- @Initializer
- TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
- this.sentenceParser = sentenceParser;
- this.sentenceTranslator = sentenceTranslator;
- }
-
- public String translate(String text) {
- StringBuilder sb = new StringBuilder();
- for (String sentence: sentenceParser.parse(text)) {
- sb.append(sentenceTranslator.translate(sentence));
- }
- return sb.toString();
- }
-
+ public String translate(String text) {
+ StringBuilder sb = new StringBuilder();
+ for (String sentence: sentenceParser.parse(text)) {
+ sb.append(sentenceTranslator.translate(sentence));
+ }
+ return sb.toString();
+ }
}]]></programlisting>
- <para>We may obtain an instance of <literal>TextTranslator</literal> by
- injecting it into a Web Bean, Servlet or EJB:</para>
+ <para>
+ But wait! <literal>TextTranslator</literal> does not have a constructor with no parameters! Is it still a bean?
+ If you remember, a class that does not have a constructor with no parameters can still be a bean if it has a
+ constructor annotated <literal>@Inject</literal>.
+ </para>
+
+ <para>
+ As you've guessed, the <literal>@Inject</literal> annotation has something to do with dependency injection!
+ <literal>@Inject</literal> may be applied to a constructor or method of a bean, and tells the bean manager to
+ call that constructor or method when instantiating the bean. The bean manager will inject other beans it finds
+ into the parameters of the constructor or method.
+ </para>
+
+ <para>
+ We may obtain an instance of <literal>TextTranslator</literal> by injecting it into a constructor, bean
+ "setter" method, producer method, observer method or field of a JavaBean or EJB session, or a field of a
+ Servlet. The injection is based on the type of the injection point, not the name of the field, method or
+ argument.
+ </para>
+
+ <para>
+ Let's create a UI controller bean that uses field injection to obtain an instance of the
+ <literal>TextTranslator</literal>, translating the text entered by a user:
+ </para>
- <programlisting role="JAVA"><![CDATA[@Initializer
-public setTextTranslator(TextTranslator textTranslator) {
- this.textTranslator = textTranslator;
+ <programlisting role="JAVA"><![CDATA[@Named @RequestScoped
+public class TranslateController {
+ @Inject private TextTranslator textTranslator;
+
+ private String inputText;
+ private String translation;
+
+ // action method, perhaps
+ public void translate() {
+ translation = textTranslator.translate(inputText);
+ }
+
+ public String getInputText() {
+ return inputText;
+ }
+
+ public void setInputText(String text) {
+ this.inputText = text;
+ }
+
+ public String getTranslation() {
+ return translation;
+ }
}]]></programlisting>
- <para>Alternatively, we may obtain an instance by directly calling a method
- of the Web Bean manager:</para>
+ <para>
+ Notice that it isn't necessary to create a getter or setter method to inject one bean into another. CDI can
+ access the field directly (even if it's private!), which should help eliminate some wasteful code. The name of
+ the field is arbitrary. It's the field's type that determines what is injected.
+ </para>
+
+ <para>
+ At system initialization time, the bean manager must validate that exactly one bean exists which satisfies each
+ injection point. In our example, if no implementation of <literal>Translator</literal> is available -- if
+ the <literal>SentenceTranslator</literal> EJB was not deployed -- the bean manager would throw an
+ <literal>UnsatisfiedDependencyException</literal>. If more than one implementation of
+ <literal>Translator</literal> were available, the bean manager would throw an
+ <literal>AmbiguousDependencyException</literal>. The same for the <literal>TextTranslator</literal> injection
+ point.
+ </para>
- <programlisting role="JAVA"><![CDATA[TextTranslator tt = manager.getInstanceByType(TextTranslator.class);]]></programlisting>
+ <para>
+ Now we are starting to venture off into the details, so let's pause and examine a bean's anatomy. What aspects
+ of the bean are significant, and what gives it its identity?
+ </para>
- <para>But wait: <literal>TextTranslator</literal> does not have a constructor
- with no parameters! Is it still a Web Bean? Well, a class that does not have a
- constructor with no parameters can still be a Web Bean if it has a constructor
- annotated <literal>@Initializer</literal>.</para>
-
- <para>As you've guessed, the <literal>@Initializer</literal> annotation has
- something to do with dependency injection! <literal>@Initializer</literal>
- may be applied to a constructor or method of a Web Bean, and tells the
- Web Bean manager to call that constructor or method when instantiating the
- Web Bean. The Web Bean manager will inject other Web Beans to the parameters
- of the constructor or method.</para>
-
- <para>At system initialization time, the Web Bean manager must validate that
- exactly one Web Bean exists which satisfies each injection point. In our example,
- if no implementation of <literal>Translator</literal> available — if the
- <literal>SentenceTranslator</literal> EJB was not deployed — the Web Bean
- manager would throw an <literal>UnsatisfiedDependencyException</literal>. If
- more than one implementation of <literal>Translator</literal> was available,
- the Web Bean manager would throw an
- <literal>AmbiguousDependencyException</literal>.</para>
-
- </section>
+ </section>
+
+ <!-- mention alternatives here? -->
+ <section id="bean-anatomy">
+ <title>The anatomy of a bean</title>
-<section>
- <title>What is a Web Bean?</title>
+ <para>
+ A bean is an application class that contains business logic. It may be called directly from Java code, or it
+ may be invoked via Unified EL. A bean may access transactional resources. Dependencies between beans are
+ managed automatically by the bean manager. Most beans are <emphasis>stateful</emphasis> and
+ <emphasis>contextual</emphasis>. The lifecycle of a bean is always managed by the bean manager.
+ </para>
- <para>So what, <emphasis>exactly</emphasis>, is a Web Bean?</para>
+ <para>
+ Let's back up a second. What does it really mean to be <emphasis>contextual</emphasis>? Since beans may be
+ stateful, it matters <emphasis>which</emphasis> bean instance I have. Unlike a stateless component model (for
+ example, stateless session beans) or a singleton component model (such as servlets, or singleton beans),
+ different clients of a bean see the bean in different states. The client-visible state depends upon which
+ instance of the bean the client has a reference to.
+ </para>
- <para>A Web Bean is an application class that contains business logic. A Web
- Bean may be called directly from Java code, or it may be invoked via Unified EL.
- A Web Bean may access transactional resources. Dependencies between Web Beans
- are managed automatically by the Web Bean manager. Most Web Beans are
- <emphasis>stateful</emphasis> and <emphasis>contextual</emphasis>. The lifecycle
- of a Web Bean is always managed by the Web Bean manager.</para>
+ <para>
+ However, like a stateless or singleton model, but <emphasis>unlike</emphasis> stateful session beans, the
+ client does not control the lifecycle of the instance by explicitly creating and destroying it. Instead, the
+ <emphasis>scope</emphasis> of the bean determines:
+ </para>
- <para>Let's back up a second. What does it really mean to be "contextual"? Since
- Web Beans may be stateful, it matters <emphasis>which</emphasis> bean instance I
- have. Unlike a stateless component model (for example, stateless session beans)
- or a singleton component model (such as servlets, or singleton beans), different
- clients of a Web Bean see the Web Bean in different states. The client-visible
- state depends upon which instance of the Web Bean the client has a reference to.</para>
-
- <para>However, like a stateless or singleton model, but <emphasis>unlike</emphasis>
- stateful session beans, the client does not control the lifecycle of the instance
- by explicitly creating and destroying it. Instead, the <emphasis>scope</emphasis>
- of the Web Bean determines:</para>
-
- <itemizedlist>
- <listitem>
- <para>the lifecycle of each instance of the Web Bean and</para>
- </listitem>
- <listitem>
- <para>which clients share a reference to a particular instance of the Web
- Bean.</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>the lifecycle of each instance of the bean and</para>
+ </listitem>
+ <listitem>
+ <para>which clients share a reference to a particular instance of the bean.</para>
+ </listitem>
+ </itemizedlist>
- <para>For a given thread in a Web Beans application, there may be an
- <emphasis>active context</emphasis> associated with the scope of the Web Bean.
- This context may be unique to the thread (for example, if the Web Bean is request
- scoped), or it may be shared with certain other threads (for example, if the Web
- Bean is session scoped) or even all other threads (if it is application scoped).</para>
+ <para>
+ For a given thread in a CDI application, there may be an <emphasis>active context</emphasis> associated with
+ the scope of the bean. This context may be unique to the thread (for example, if the bean is request scoped),
+ or it may be shared with certain other threads (for example, if the bean is session scoped) or even all other
+ threads (if it is application scoped).
+ </para>
- <para>Clients (for example, other Web Beans) executing in the same context will
- see the same instance of the Web Bean. But clients in a different context will
- see a different instance.</para>
+ <para>
+ Clients (for example, other beans) executing in the same context will see the same instance of the bean. But
+ clients in a different context may see a different instance (depending on the relationship between the
+ contexts).
+ </para>
- <para>One great advantage of the contextual model is that it allows stateful
- Web Beans to be treated like services! The client need not concern itself with
- managing the lifecycle of the Web Bean it is using, <emphasis>nor does it even
- need to know what that lifecyle is.</emphasis> Web Beans interact by passing
- messages, and the Web Bean implementations define the lifecycle of their own state.
- The Web Beans are loosely coupled because:</para>
+ <para>
+ One great advantage of the contextual model is that it allows stateful beans to be treated like services! The
+ client need not concern itself with managing the lifecycle of the bean it's using, <emphasis>nor does it even
+ need to know what that lifecyle is.</emphasis> Beans interact by passing messages, and the bean implementations
+ define the lifecycle of their own state. The beans are loosely coupled because:
+ </para>
- <itemizedlist>
- <listitem>
- <para>they interact via well-defined public APIs</para>
- </listitem>
- <listitem>
- <para>their lifecycles are completely decoupled</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>they interact via well-defined public APIs</para>
+ </listitem>
+ <listitem>
+ <para>their lifecycles are completely decoupled</para>
+ </listitem>
+ </itemizedlist>
- <para>We can replace one Web Bean with a different Web Bean that implements the
- same API and has a different lifecycle (a different scope) without affecting the
- other Web Bean implementation. In fact, Web Beans defines a sophisticated
- facility for overriding Web Bean implementations at deployment time, as we will
- see in <xref linkend="deploymenttypes"/>.</para>
+ <para>
+ We can replace one bean with another different bean that implements the same interface and has a different lifecycle
+ (a different scope) without affecting the other bean implementation. In fact, CDI defines a simple facility for
+ overriding bean implementations at deployment time, as we will see in <xref linkend="alternatives"/> (FIXREF).
+ </para>
- <para>Note that not all clients of a Web Bean are Web Beans. Other objects
- such as Servlets or Message-Driven Beans — which are by nature not injectable,
- contextual objects — may also obtain references to Web Beans by injection.</para>
+ <para>
+ Note that not all clients of a bean are beans themselves. Other objects such as Servlets or Message-Driven
+ Beans -- which are by nature not injectable, contextual objects -- may also obtain references to beans by
+ injection.
+ </para>
- <para>Enough hand-waving. More formally, according to the spec:</para>
+ <para>Enough hand-waving. More formally, the anatomy of a bean, according to the spec:</para>
- <blockquote>
+ <blockquote>
- <para>A Web Bean comprises:</para>
+ <para>A bean comprises of the following attributes:</para>
- <itemizedlist>
- <listitem><para>A (nonempty) set of API types</para></listitem>
- <listitem><para>A (nonempty) set of binding annotation types</para></listitem>
- <listitem><para>A scope</para></listitem>
- <listitem><para>A deployment type</para></listitem>
- <listitem><para>Optionally, a Web Bean name</para></listitem>
- <listitem><para>A set of interceptor binding types</para></listitem>
- <listitem><para>A Web Bean implementation</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>A (nonempty) set of bean types</para></listitem>
+ <listitem><para>A (nonempty) set of qualifiers</para></listitem>
+ <listitem><para>A scope</para></listitem>
+ <listitem><para>A deployment type</para></listitem>
+ <listitem><para>Optionally, a bean EL name</para></listitem>
+ <listitem><para>A set of interceptor bindings</para></listitem>
+ <listitem><para>A bean implementation</para></listitem>
+ </itemizedlist>
- </blockquote>
+ </blockquote>
- <para>Let's see what some of these terms mean, to the Web Bean developer.</para>
+ <para>Let's see what some of these terms mean, to the CDI developer.</para>
-<section>
- <title>API types, binding types and dependency injection</title>
+ <section>
+ <title>Bean types, qualifiers and dependency injection</title>
- <para>Web Beans usually acquire references to other Web Beans via dependency
- injection. Any injected attribute specifies a "contract" that must be
- satisfied by the Web Bean to be injected. The contract is:</para>
+ <para>
+ Beans usually acquire references to other beans via dependency injection. Any injected attribute specifies a
+ "contract" that must be satisfied by the bean to be injected. The contract is:
+ </para>
- <itemizedlist>
- <listitem><para>an API type, together with</para></listitem>
- <listitem><para>a set of binding types.</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>a bean type, together with</para></listitem>
+ <listitem><para>a set of qualifiers.</para></listitem>
+ </itemizedlist>
- <para>An API is a user-defined class or interface. (If the Web Bean is an
- EJB session bean, the API type is the <literal>@Local</literal> interface or
- bean-class local view). A binding type represents some client-visible semantic
- that is satisfied by some implementations of the API and not by others.</para>
+ <para>
+ A bean type is a user-defined class or interface; types that are client-visible. If the bean is an EJB
+ session bean, the bean type is the <literal>@Local</literal> interface or bean-class local view. A bean may
+ have multiple bean types. For example, the following bean has four bean types:
+ </para>
- <para>Binding types are represented by user-defined annotations that are
- themselves annotated <literal>@BindingType</literal>. For example, the following
- injection point has API type <literal>PaymentProcessor</literal> and binding
- type <literal>@CreditCard</literal>:</para>
+ <programlisting role="JAVA"><![CDATA[public class BookShop extends Business implements Shop<Book> {
+ ...
+}]]></programlisting>
-<programlisting role="JAVA"><![CDATA[@CreditCard PaymentProcessor paymentProcessor]]></programlisting>
+ <para>
+ The bean types are <literal>BookShop</literal>, <literal>Business</literal> and
+ <literal>Shop<Book></literal>, as well as the implicit type <literal>java.lang.Object</literal>.
+ (Notice that a parameterized type is a legal bean type). Meanwhile, this session bean has only the local
+ interfaces <literal>BookShop</literal>, <literal>Auditable</literal> and <literal>java.lang.Object</literal>
+ as bean types, since the bean class, <literal>BookShopBean</literal> is not a client-visible type.
+ </para>
- <para>If no binding type is explicitly specified at an injection point, the
- default binding type <literal>@Current</literal> is assumed.</para>
+ <programlisting role="JAVA"><![CDATA[@Stateful
+public class BookShopBean extends Business implements BookShop, Auditable {
+ ...
+}]]></programlisting>
- <para>For each injection point, the Web Bean manager searches for a Web Bean
- which satisfies the contract (implements the API, and has all the binding
- types), and injects that Web Bean.</para>
+ <note>
+ <para>
+ Most bean types you can probably figure out. One gotcha is primitive types. All primitive types are assumed
+ to be identical to their corresponding wrapper types in <literal>java.lang</literal>.
+ </para>
+ </note>
- <para>The following Web Bean has the binding type <literal>@CreditCard</literal>
- and implements the API type <literal>PaymentProcessor</literal>. It could
- therefore be injected to the example injection point:</para>
+ <para>
+ Bean types may be restricted to an explicit set by annotating the bean with the <literal>@Typed</literal>
+ annotation and listing the bean types in the value of the annotation. For instance, this bean has been
+ restricted to a single bean type, <literal>Shop</literal>:
+ </para>
-<programlisting role="JAVA"><![CDATA[@CreditCard
-public class CreditCardPaymentProcessor
- implements PaymentProcessor { ... }]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[(a)Typed(Shop.class)
+public class BookShop extends Business implements Shop<Book> {
+ ...
+}]]></programlisting>
- <para>If a Web Bean does not explicitly specify a set of binding types, it has
- exactly one binding type: the default binding type <literal>@Current</literal>.</para>
+ <para>
+ The bean types alone often do not provide enough information for the bean manager to know which bean to
+ inject. For instance, say you have two implementations of the <literal>PaymentProcessor</literal> interface:
+ <literal>CreditCardPaymentProcessor</literal> and <literal>DebitPaymentProcessor</literal>. Injecting into a
+ field of type <literal>PaymentProcessor</literal> introduces an ambigious condition. In these cases, the
+ bean manager must rely on some client-visible semantic that is satisified by one implementation of the bean
+ type, but not by others. That semantic is called a qualifier.
+ </para>
- <para>Web Beans defines a sophisticated but intuitive <emphasis>resolution
- algorithm</emphasis> that helps the container decide what to do if there is more
- than one Web Bean that satisfies a particular contract. We'll get into the
- details in <xref linkend="injection"/>.</para>
+ <para>
+ Qualifiers are represented by user-defined annotations that are themselves annotated with
+ <literal>@Qualifer</literal>. These annotations extend the type system in Java to let you further qualify
+ the type without having to fall back to string-based names as many dependency injection frameworks use.
+ Here's an example of a qualifier annotation:
+ </para>
-</section>
+ <programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+@Qualifier
+public @interface CreditCard {}]]></programlisting>
-<section>
- <title>Deployment types</title>
+ <para>
+ You may not be used to seeing the definition of an annotation. In fact, this might be the first time you
+ have encountered one. With CDI, they will become very familiar artifact as you will be creating them often.
+ Pay attention to the names of the built-in annotations in CDI and EJB.
+ </para>
+
+ <tip>
+ <para>
+ You'll notice that they are all adjectives. You are encouraged to follow this convention when creating
+ your custom annotations, since they serve to describe the behaviors and roles of the class.
+ </para>
+ </tip>
+
+ <para>
+ Now that we have defined a qualifier annotation, we can use it. The following injection point has the bean
+ type <literal>PaymentProcessor</literal> and qualifier <literal>@CreditCard</literal>:
+ </para>
- <para><emphasis>Deployment types</emphasis> let us classify our Web Beans by
- deployment scenario. A deployment type is an annotation that represents a particular
- deployment scenario, for example <literal>@Mock</literal>, <literal>@Staging</literal>
- or <literal>@AustralianTaxLaw</literal>. We apply the annotation to Web Beans which
- should be deployed in that scenario. A deployment type allows a whole set of Web Beans
- to be conditionally deployed, with a just single line of configuration.</para>
+ <programlisting role="JAVA"><![CDATA[@Inject @CreditCard PaymentProcessor paymentProcessor]]></programlisting>
- <para>Many Web Beans just use the default deployment type <literal>@Production</literal>,
- in which case no deployment type need be explicitly specified. All three Web Bean
- in our example have the deployment type <literal>@Production</literal>.</para>
+ <note>
+ <para>
+ If no qualifier is specified at an injection point, the default qualifier, <literal>@Default</literal>, is
+ assumed.
+ </para>
+ </note>
- <para>In a testing environment, we might want to replace the <literal>SentenceTranslator</literal>
- Web Bean with a "mock object":</para>
+ <para>
+ For each injection point, the bean manager searches for a bean which satisfies the contract, meaning it
+ matches the bean time and all the qualifiers. It then injects that instance.
+ </para>
-<programlisting role="JAVA"><![CDATA[@Mock
-public class MockSentenceTranslator implements Translator {
- public String translate(String sentence) {
- return "Lorem ipsum dolor sit amet";
- }
-}]]></programlisting>
+ <para>
+ We've seen how to indicate that you want to inject qualified bean. But how do you actually qualify the bean?
+ By using the annotation, of course! The following bean has the qualifier <literal>@CreditCard</literal>
+ and implements the bean type <literal>PaymentProcessor</literal>. Therefore, it satisfies our qualified
+ injection point:
+ </para>
+ <programlisting role="JAVA"><![CDATA[@CreditCard
+public class CreditCardPaymentProcessor
+ implements PaymentProcessor { ... }]]></programlisting>
- <para>We would enable the deployment type <literal>@Mock</literal> in our testing
- environment, to indicate that <literal>MockSentenceTranslator</literal> and any other
- Web Bean annotated <literal>@Mock</literal> should be used.</para>
+ <note>
+ <para>
+ If a bean does not explicitly specify a qualifier, it has exactly one qualifier, the default qualifier,
+ <literal>@Default</literal>.
+ </para>
+ </note>
- <para>We'll talk more about this unique and powerful feature in
- <xref linkend="deploymenttypes"/>.</para>
+ <para>
+ CDI defines a sophisticated, yet intuitive <emphasis>resolution algorithm</emphasis> that helps the
+ container decide what to do if there is more than one bean that satisfies a particular contract. We'll get
+ into the details in <xref linkend="injection"/>.
+ </para>
-</section>
+ </section>
-<section>
- <title>Scope</title>
+ <section>
+ <title>Scope</title>
+ <!-- I wonder whether the explaination of contextual above would fit better here -->
- <para>The <emphasis>scope</emphasis> defines the lifecycle and visibility
- of instances of the Web Bean. The Web Beans context model is extensible,
- accommodating arbitrary scopes. However, certain important scopes are
- built-in to the specification, and provided by the Web Bean manager. A
- scope is represented by an annotation type.</para>
+ <para>
+ The <emphasis>scope</emphasis> of a bean defines the lifecycle and visibility of instances created from it.
+ The CDI context model is extensible, accommodating arbitrary scopes. However, certain important scopes are
+ built-in to the specification, and provided by the bean manager. Each scope is represented by an annotation
+ type.
+ </para>
- <para>For example, any web application may have <emphasis>session scoped</emphasis>
- Web Beans:</para>
+ <para>
+ For example, any web application may have <emphasis>session scoped</emphasis> bean:
+ </para>
-<programlisting role="JAVA"><![CDATA[@SessionScoped
+ <programlisting role="JAVA"><![CDATA[@SessionScoped
public class ShoppingCart { ... }]]></programlisting>
- <para>An instance of a session scoped Web Bean is bound to a user session
+ <para>An instance of a session-scoped bean is bound to a user session
and is shared by all requests that execute in the context of that session.</para>
- <para>By default, Web Beans belong to a special scope called the
- <emphasis>dependent pseudo-scope</emphasis>. Web Beans with this scope are
- pure dependent objects of the object into which they are injected, and their
- lifecycle is bound to the lifecycle of that object.</para>
+ <note>
+ <para>
+ Keep in mind that once a bean is bound to a context, it remains in that context until the context is
+ destroyed. There is no way to explicitly remove a bean from a context. If you don't the bean to live in
+ the session indefinitely, consider using another scope such as the request or conversation scope instead.
+ </para>
+ </note>
- <para>We'll talk more about scopes in <xref linkend="scopescontexts"/>.</para>
+ <para>
+ If a scope is not explicitly specified, then the bean belongs to a special scope called the
+ <emphasis>dependent pseudo-scope</emphasis>. Beans with this scope live to serve the bean into which they
+ are injected, which means their life cycle is bound to the life cycle of that object.
+ </para>
-</section>
+ <para>We'll talk more about scopes in <xref linkend="scopescontexts"/>.</para>
-<section>
- <title>Web Bean names and Unified EL</title>
+ </section>
- <para>A Web Bean may have a <emphasis>name</emphasis>, allowing it to be
- used in Unified EL expressions. It's easy to specify the name of a Web
- Bean:</para>
+ <section>
+ <title>EL name</title>
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Named("cart")
+ <para>
+ If you want to reference a bean outside of Java, such as in JSF view, you must assign the bean a
+ <emphasis>name</emphasis>. The name is used as the EL name of the bean, allowing the bean to be used
+ in a Unified EL expression.
+ </para>
+
+ <para>
+ The name is specified using the <literal>@Named</literal> annotation, as shown here:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@SessionScoped @Named("cart")
public class ShoppingCart { ... }]]></programlisting>
- <para>Now we can easily use the Web Bean in any JSF or JSP page:</para>
+ <para>Now we can easily use the bean in any JSF or JSP page:</para>
-<programlisting role="HTML"><![CDATA[<h:dataTable value="#{cart.lineItems}" var="item">
- ....
+ <programlisting role="XML"><![CDATA[<h:dataTable value="#{cart.lineItems}" var="item">
+ ...
</h:dataTable>]]></programlisting>
- <para>It's even easier to just let the name be defaulted by the Web Bean
- manager:</para>
+ <note>
+ <para>
+ The <literal>@Named</literal> annotation is not what makes the class a bean. Most classes in a bean
+ archive are already recognized as beans. The <literal>@Named</literal> annotation just makes it
+ possible to reference the bean from the EL, most commonly from a JSF view.
+ </para>
+ </note>
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Named
+ <para>
+ If you want, you can let CDI select a name for you by leaving off the
+ value of the <literal>@Named</literal> annotation:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@SessionScoped @Named
public class ShoppingCart { ... }]]></programlisting>
- <para>In this case, the name defaults to <literal>shoppingCart</literal> — the
- unqualified class name, with the first character changed to lowercase.</para>
+ <para>
+ The name defaults to the unqualified class name, decapitalized; in this case,
+ <literal>shoppingCart</literal>.
+ </para>
-</section>
+ </section>
-<section>
- <title>Interceptor binding types</title>
-
- <para>Web Beans supports the interceptor functionality defined by EJB 3,
- not only for EJB beans, but also for plain Java classes. In addition,
- Web Beans provides a new approach to binding interceptors to EJB beans
- and other Web Beans.</para>
-
- <para>It remains possible to directly specify the interceptor class via
- use of the <literal>@Interceptors</literal> annotation:</para>
-
-<programlisting role="JAVA"><![CDATA[@SessionScoped
-(a)Interceptors(TransactionInterceptor.class)
-public class ShoppingCart { ... }]]></programlisting>
+ <section>
+ <title>Alternatives</title>
- <para>However, it is more elegant, and better practice, to indirect the
- interceptor binding through an <emphasis>interceptor binding
- type</emphasis>:</para>
-
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Transactional
+ <para>
+ There are cases when you want to replace one bean implementation with another at deployment time. For
+ instance, you may want to use a mock implementation in a testing environment. An
+ <emphasis>alternative</emphasis> may be declared by annotating the bean class or producer method or field
+ with the <literal>@Alternative</literal> annotation.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Alternative
+public class MockPaymentProcessor extends PaymentProcessorImpl { ... }]]></programlisting>
+
+ <para>
+ You then enable the alternative using the CDI deployment descriptor, META-INF/beans.xml, in the classpath
+ entry in which you intent to use it. An alternative must be explicitly selected in every bean deployment
+ archive in which the alternative should be available for injection, lookup and EL resolution.
+ </para>
+
+ <para>
+ Details on how to enable alternative beans, and how you can use them to specialize (override) beans and
+ producer methods is covered in <xref linkend="specialization"/>. CDI is very flexible when it comes
+ alternatives that are selected at deployment time.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Interceptor binding types</title>
+
+ <para>
+ Since the introduction of the Managed Bean specification in Java EE 6, interceptors are available on
+ JavaBeans in additionn to EJB session beans. That's right, you no longer have to create an EJB just to
+ intercept method calls. Holler. So what does CDI have to offer? Well, a lot actually. Let's cover some
+ background.
+ </para>
+
+ <para>
+ The way that interceptors are defined in Java EE 5 is counter-intuitive. You are required to specify the
+ <emphasis>implementation</emphasis> of the interceptor directly on the <emphasis>implementation</emphasis>
+ of the EJB, either in the <literal>@Interceptors</literal> annotation or in the XML descriptor. You might as
+ well just put the interceptor code <emphasis>in</emphasis> the implementation. Second, the order in which
+ the interceptors are applied is taken from the order in which they are declared in the annotation or the XML
+ descriptor. Perhaps this isn't so bad if you're applying the interceptors to a single bean. But, if you are
+ applying them repeatly, then there is a chance that you'll inadvertly define a different order for different
+ beans. Now that is a problem.
+ </para>
+
+ <para>
+ CDI provides a new approach to binding interceptors to beans that introduces a level of abstraction (and
+ thus control). You define a special kind of annotation called an <emphasis>interceptor binding
+ type</emphasis> whose name describes the role of the interceptor, in this case to add transaction support:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@InterceptorBinding
+@Inherited
+@Target( { TYPE, METHOD })
+@Retention(RUNTIME)
+public @interface Transactional {}]]></programlisting>
+
+ <para>
+ Then you apply the annotation to the class whose methods you wish to have intercepted.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@SessionScoped @Transactional
public class ShoppingCart { ... }]]></programlisting>
- <para>We'll discuss Web Beans interceptors and decorators in
- <xref linkend="interceptors"/> and <xref linkend="decorators"/>.</para>
+ <para>
+ Where is the interceptor? You match the interceptor(s) to apply to the bean by also annotating the
+ interceptor class. Never do the two implementations (bean and interceptor) come in direct contact.
+ Activating and ordering of the interceptors is then controlled by the XML descriptor, one of the few times
+ XML is warranted.
+ </para>
+
+ <para>
+ We'll discuss bean interceptors, and their cousins, decorators, in <xref linkend="interceptors"/> and <xref
+ linkend="decorators"/>.
+ </para>
-</section>
+ </section>
-</section>
+ </section>
-<section>
- <title>What kinds of objects can be Web Beans?</title>
-
- <para>We've already seen that JavaBeans, EJBs and some other Java classes can
- be Web Beans. But exactly what kinds of objects are Web Beans?</para>
-
- <section>
- <title>Simple Web Beans</title>
-
- <para>The Web Beans specification says that a concrete Java class is a
- <emphasis>simple</emphasis> Web Bean if:</para>
-
- <itemizedlist>
- <listitem>
- <para>it is not an EE container-managed component, like an EJB, a Servlet
- or a JPA entity,</para>
- </listitem>
- <listitem>
- <para>it is not a non-static static inner class,</para>
- </listitem>
- <listitem>
- <para>it is not a parameterized type, and</para>
- </listitem>
- <listitem>
- <para>it has a constructor with no parameters, or a constructor annotated
- <literal>@Initializer</literal>.</para>
- </listitem>
- </itemizedlist>
-
- <para>Thus, almost every JavaBean is a simple Web Bean.</para>
-
- <para>Every interface implemented directly or indirectly by a simple Web Bean
- is an API type of the simple Web Bean. The class and its superclasses are also
- API types.</para>
-
- </section>
-
- <section>
- <title>Enterprise Web Beans</title>
-
- <para>The specification says that all EJB 3-style session and singleton beans
- are <emphasis>enterprise</emphasis> Web Beans. Message driven beans are not
- Web Beans — since they are not intended to be injected into other
- objects — but they can take advantage of most of the functionality of Web
- Beans, including dependency injection and interceptors.</para>
-
- <para>Every local interface of an enterprise Web Bean that does not have a
- wildcard type parameter or type variable, and every one of its superinterfaces,
- is an API type of the enterprise Web Bean. If the EJB bean has a bean class
- local view, the bean class, and every one of its superclasses, is also an API
- type.</para>
-
- <para>Stateful session beans should declare a remove method with no parameters
- or a remove method annotated <literal>@Destructor</literal>. The Web Bean
- manager calls this method to destroy the stateful session bean instance at the
- end of its lifecycle. This method is called the <emphasis>destructor</emphasis>
- method of the enterprise Web Bean.</para>
-
-<programlisting role="JAVA"><![CDATA[@Stateful @SessionScoped
-public class ShoppingCart {
+ <section>
+ <title>What kinds of classes can be beans?</title>
+
+ <para>
+ We've already seen that JavaBeans and EJBs can be (CDI) beans. Is that the whole story? Let's start from what
+ we know, and go from there.
+ </para>
+
+ <section>
+ <title>Managed beans</title>
- ...
-
- @Remove
- public void destroy() {}
+ <para>
+ A managed bean is a bean that is implemented by almost any Java class. This class is called the bean class
+ of the managed bean. The basic lifecycle and semantics of a managed bean is defined by the Managed Beans
+ specification. If the class is not picked up as a managed bean by the container, then CDI will allow it
+ to be a bean if:
+ </para>
-}]]></programlisting>
+ <itemizedlist>
+ <listitem>
+ <para>It is not a non-static inner class.</para>
+ </listitem>
+ <listitem>
+ <para>It is a concrete class, or is annotated <literal>@Decorator</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>
+ It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in
+ ejb-jar.xml.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ It has an appropriate constructor -- either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>the class has a constructor with no parameters, or</para>
+ </listitem>
+ <listitem>
+ <para>the class declares a constructor annotated <literal>@Inject</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
- <para>So when should we use an enterprise Web Bean instead of a simple Web Bean?
- Well, whenever we need the advanced enterprise services offered by EJB, such
- as:</para>
-
-
- <itemizedlist>
- <listitem>
- <para>method-level transaction management and security,</para>
- </listitem>
- <listitem>
- <para>concurrency management,</para>
- </listitem>
- <listitem>
- <para>instance-level passivation for stateful session beans and
- instance-pooling for stateless session beans,</para>
- </listitem>
- <listitem>
- <para>remote and web service invocation, and</para>
- </listitem>
- <listitem>
- <para>timers and asynchronous methods,</para>
- </listitem>
- </itemizedlist>
-
- <para>we should use an enterprise Web Bean. When we don't need any of these things,
- a simple Web Bean will serve just fine.</para>
-
- <para>Many Web Beans (including any session or application scoped Web Bean) are
- available for concurrent access. Therefore, the concurrency management provided
- by EJB 3.1 is especially useful. Most session and application scoped Web Beans
- should be EJBs.</para>
-
- <para>Web Beans which hold references to heavy-weight resources, or hold a lot
- of internal state benefit from the advanced container-managed lifecycle defined
- by the EJB <literal>@Stateless</literal>/<literal>@Stateful</literal>/<literal>@Singleton</literal>
- model, with its support for passivation and instance pooling.</para>
-
- <para>Finally, it's usually obvious when method-level transaction management,
- method-level security, timers, remote methods or asynchronous methods are needed.</para>
-
- <para>It's usually easy to start with simple Web Bean, and then turn it into an
- EJB, just by adding an annotation: <literal>@Stateless</literal>,
- <literal>@Stateful</literal> or <literal>@Singleton</literal>.</para>
+ <para>
+ <emphasis>Unlike</emphasis> the managed bean definition, no special declaration is required to define a
+ managed bean. CDI takes advantage of the fact that the Managed Bean specification allows companion
+ specifications to relax the requirement of having to add the <literal>@ManagedBean</literal> annotation.
+ </para>
- </section>
-
- <section>
- <title>Producer methods</title>
+ <para>
+ Some managed beans are much more. Those are the session beans. While still technically managed beans, they
+ have enough additional, enterprise features, that we consider them to be their own kind.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Session beans</title>
- <para>A <emphasis>producer method</emphasis> is a method that is called by the
- Web Bean manager to obtain an instance of the Web Bean when no instance exists
- in the current context. A producer method lets the application take full control
- of the instantiation process, instead of leaving instantiation to the Web Bean
- manager. For example:</para>
+ <para>
+ EJB 3 session beans belong to the EJB specification. That is, the basic life cycle and semantics. Beyond
+ that, they get to participate in CDI just like any other bean. There are some restrictions about which
+ scopes can be assigned to a session bean, but other than that, they are interchangable with regular managed
+ beans. That means you can inject one session bean into another, a managed bean into a session bean, a
+ session bean into a managed bean, have a managed bean observe an event raised by a session bean, and so on.
+ </para>
-<programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Generator {
+ <note>
+ <para>
+ Message-driven and entity beans are by nature non-contextual objects and may not be injected into other
+ objects. Message-driven beans can take advantage of some CDI functionality, such as dependency injection
+ and interceptors. In fact, CDI will perform injection into any message-driven or session bean, even those
+ which are not contextual instances.
+ </para>
+ </note>
- private Random random = new Random( System.currentTimeMillis() );
-
- @Produces @Random int next() {
- return random.nextInt(100);
- }
+ <para>
+ The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their
+ superinterfaces. If the session bean has a bean class local view, the unrestricted set of bean types
+ contains the bean class and all superclasses. In addition, <literal>java.lang.Object</literal> is a bean
+ type of every session bean. But, remote interfaces are <emphasis>not</emphasis> included in the set of bean
+ types.
+ </para>
+ <para>
+ Stateful session beans can define a no arguments remove method, annotated <literal>@Remove</literal>, that
+ is used by the application to indicate the instance should be destroyed. However, in a CDI environment, this
+ method can only be executed by the application if the bean is dependent-scoped. Otherwise, it's illegal for
+ the application to invoke this method.
+ </para>
+
+ <para>
+ So, when should we use a session instead of a basic managed bean? Whenever we need the advanced enterprise
+ services offered by EJB, such as:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>method-level transaction management and security,</para>
+ </listitem>
+ <listitem>
+ <para>concurrency management,</para>
+ </listitem>
+ <listitem>
+ <para>instance-level passivation for stateful session beans and
+ instance-pooling for stateless session beans,</para>
+ </listitem>
+ <listitem>
+ <para>remote and web service invocation, and</para>
+ </listitem>
+ <listitem>
+ <para>timers and asynchronous methods,</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>When we don't need any of these things, a basic managed bean will serve just fine.</para>
+
+ <para>
+ Many beans (including any session or application scoped bean) are available for concurrent access.
+ Therefore, the concurrency management provided by EJB 3.1 is especially useful. Most session and application
+ scoped beans should be EJBs.
+ </para>
+
+ <para>
+ Beans which hold references to heavy-weight resources, or hold a lot of internal state benefit from the
+ advanced container-managed lifecycle defined by the EJB
+ <literal>@Stateless</literal>/<literal>@Stateful</literal>/<literal>@Singleton</literal> model, with its
+ support for passivation and instance pooling.
+ </para>
+
+ <para>
+ Finally, it's usually obvious when method-level transaction management, method-level security, timers,
+ remote methods or asynchronous methods are needed.
+ </para>
+
+ <para>
+ The point is, you use a session bean when you need the services it provides, not just because you want to
+ use dependency injection, life cycle management, or interceptors. The Java EE programming model makes a
+ whole lot more sense now; you won't need to go off and invent your own bean container to make programming
+ in Java EE palatable.
+ </para>
+
+ <para>
+ In fact, it's easy to start with simple managed bean, and later turn it into an EJB just by adding one of
+ the following annotations: <literal>@Stateless</literal>, <literal>@Stateful</literal> or
+ <literal>@Singleton</literal>.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Producer methods</title>
+
+ <para>
+ Surely not everything you want to inject can be a bean class. What if you need to inject the implementation
+ of an API that varies at runtime? And how would you inject objects that are created by another mechanism,
+ such as a JPA result? Fortunately, the CDI specification recognized these and other cases and introduced the
+ concept of a producer method.
+ </para>
+
+ <para>
+ A <emphasis>producer method</emphasis> is a method on a bean that is used as a bean source, meaning the
+ method itself describes the bean and the bean manager invokes the method to obtain an instance of the bean
+ when no instance exists in its specified context. A producer method lets the application take full control
+ of the instantiation process, specifically when:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the objects to be injected are not required to be instances of beans, or
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the concrete type of the objects to be injected may vary at runtime, or
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the objects require some custom initialization that is not performed by the bean constructor.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ For example:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class RandomNumberGenerator {
+
+ private Random random = new Random(System.currentTimeMillis());
+
+ @Produces @Named @Random int getRandomNumber() {
+ return random.nextInt(100);
+ }
+
}]]></programlisting>
- <para>The result of a producer method is injected just like any other Web Bean.</para>
+ <para>
+ Obviously, you cannot define a bean that is itself a random number. A producer method allows you do define
+ its result as a bean, in this case an <literal>Integer</literal> with qualifier <literal>@Random</literal>,
+ scope <literal>@Dependent</literal> (implied) and name <literal>randomNumber</literal> (derived from bean
+ property convention; otherwise it would be the same as the method name). It can be injected just like any
+ other bean:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject @Random int randomNumber;]]></programlisting>
- <programlisting role="JAVA"><![CDATA[@Random int randomNumber]]></programlisting>
-
- <para>The method return type and all interfaces it extends/implements directly or indirectly
- are API types of the producer method. If the return type is a class, all superclasses are
- also API types.</para>
-
- <para>Some producer methods return objects that require explicit destruction:</para>
-
-<programlisting role="JAVA"><![CDATA[@Produces @RequestScoped Connection connect(User user) {
- return createConnection( user.getId(), user.getPassword() );
+ <para>
+ or used in a Unified EL expression:
+ </para>
+
+ <programlisting><![CDATA[Your raffle number is #{randomNumber}.]]></programlisting>
+
+ <para>
+ A producer method must be a non-abstract method of a managed bean class or session bean class. A producer
+ method may be either static or non-static. If the bean is a session bean, the producer method must be either
+ a business method of the EJB or a static method of the bean class.
+ </para>
+
+ <para>
+ The bean types of a producer method depend upon the method return type:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ If the return type is an interface, the unrestricted set of bean types contains the return type, all
+ interfaces it extends directly or indirectly and <literal>java.lang.Object</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a return type is primitive or is a Java array type, the unrestricted set of bean types contains
+ exactly two types: the method return type and <literal>java.lang.Object</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the return type is a class, the unrestricted set of bean types contains the return type, every
+ superclass and all interfaces it implements directly or indirectly.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Some producer methods return objects that require explicit destruction:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @RequestScoped Connection connect(User user) {
+ return createConnection(user.getId(), user.getPassword());
}]]></programlisting>
- <para>These producer methods may define matching <emphasis>disposal methods</emphasis>:</para>
-
-<programlisting role="JAVA"><![CDATA[void close(@Disposes Connection connection) {
- connection.close();
+ <para>
+ If the producer method has method arguments, as in this example, the container will look for matching beans
+ and pass them into the method automatically -- another form of dependency injection.
+ </para>
+
+ <para>Producer methods may also define matching <emphasis>disposal methods</emphasis>:</para>
+
+ <programlisting role="JAVA"><![CDATA[void close(@Disposes Connection connection) {
+ connection.close();
}]]></programlisting>
+
+ <para>
+ The disposal method is called automatically when the context ends (in this case, the end of the request).
+ The disposal method requires at least one parameter, the bean produced by the producer method. Any
+ additional parameters will be satisfied by the container.
+ </para>
+
+ <para>We'll talk much more about producer and disposal methods in <xref linkend="producermethods"/>.</para>
+
+ </section>
- <para>This disposal method is called automatically by the Web Bean manager at
- the end of the request.</para>
+ <section>
+ <title>Producer fields</title>
- <para>We'll talk much more about producer methods in <xref linkend="producermethods"/>.</para>
+ <para>
+ A <emphasis>producer field</emphasis> is a simpler alternative to a producer method and can also marry
+ dependency injection with bean definition. A producer field may be declared by annotating a field of a
+ managed bean class or session bean class with the <literal>@Produces</literal> annotation previously used on
+ producer methods.
+ </para>
- </section>
+ <programlisting role="JAVA"><![CDATA[public class Shop {
+ @Produces PaymentProcessor paymentProcessor = ....;
+ @Produces List<Product> products = ....;
+}]]></programlisting>
- <section>
- <title>JMS endpoints</title>
-
- <para>Finally, a JMS queue or topic can be a Web Bean. Web Beans relieves the
- developer from the tedium of managing the lifecycles of all the various JMS
- objects required to send messages to queues and topics. We'll discuss JMS
- endpoints in <xref linkend="jms"/>.</para>
-
- </section>
+ <para>
+ A producer field may also specify scope, name, stereotypes and/or qualifiers. It's a good way to expose
+ state from a bean as a top-level bean.
+ </para>
-</section>
+ <programlisting role="JAVA"><![CDATA[public class Shop {
+ @Produces @Wishlist @Named("wishlist") List<Product> products = ....;
+}]]></programlisting>
-</chapter>
\ No newline at end of file
+ <para>
+ The result can be injected or used in a Unified EL expression.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject @Wishlist List<Product> wishlist;]]></programlisting>
+ <programlisting role="XML"><![CDATA[<h:dataTable var="_product" value="#{wishlist}">...</h:dataTable>]]></programlisting>
+
+ <para>
+ The rules for determining the bean types of a producer field parallel the rules for producer method.
+ </para>
+
+ <para>
+ Aside from convenience, producer fields serve a specific purpose as an adapter for Java EE resources
+ injections.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Java EE resources</title>
+
+ <para>
+ Java EE 5 already introduced some support for dependency injection, in the form of resource injections. A
+ resources is either a component defined in JNDI such as a data source or a container-provided component such
+ as a persistence unit, persistence context, EJB or web service.
+ </para>
+
+ <para>
+ Naturally, there remained some mismatch with the new style of dependency injection in CDI. Most notably,
+ resource injections rely on string-based names to qualify ambigious types, and there is no real consistency
+ as to how a resource obtains its name (sometimes JNDI, other times from an XML descriptor or even a default
+ name). Producer fields turned out to be an elegant adapter to rein them in and get them to participate in
+ the CDI system just like any other injectable bean.
+ </para>
+
+ <para>
+ Producer fields have a duality in that they can both accept a standard Java EE resource injection and
+ produce a bean that can be injected into another bean in a typesafe way. Here are some examples of these
+ injection points. Notice that a qualifier annotation can be assigned at the injection point to adapt the
+ string-based name required by the injection point into a typesafe qualifier for injection elsewhere.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @WebServiceRef(lookup="java:app/service/PaymentService")
+PaymentService paymentService;]]></programlisting>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @PersistenceContext(unitName="CustomerDatabase")
+@CustomerDatabase EntityManager customerDatabasePersistenceContext;]]></programlisting>
+
+ <para>
+ These resources can then be injected in the usual way.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject PaymentService paymentService;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject @CustomerDatabase EntityManager customerDatabaseEntityManager;]]></programlisting>
+
+ <para>
+ The bean type and qualifiers of the resource are determined by the producer field declaration.
+ </para>
+
+ <para>
+ While you may have to introduce a couple extra managed beans to serve as typesafe adapters, it's well worth
+ the effort so that you can minimize the number of places in your code you have to repeat the old-style
+ dependency injection and string-based qualifiers.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Built-in beans</title>
+
+ <para>
+ Java EE gives you some other goodies in the form of built-in beans. A Java EE (or embeddable EJB) container
+ provide the following built-in beans, all of which have qualifier <literal>@Default</literal>:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a bean with bean type <literal>javax.transaction.UserTransaction</literal>, allowing injection of a
+ reference to the JTA <literal>UserTransaction</literal>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a bean with bean type <literal>javax.security.Principal</literal>, allowing injection of a
+ <literal>Principal</literal> representing the current caller identity.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a bean with bean type <literal>javax.validation.ValidationFactory</literal>, allowing injection of the
+ default <ulink src="http://jcp.org/en/jsr/detail?id=303">Bean Validation</ulink>
+ <literal>ValidationFactory</literal>, and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a bean with bean type <literal>javax.validation.Validator</literal>, allowing injection of a Validator
+ for the default Bean Validation <literal>ValidationFactory</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Aren't you excited to start using this stuff? Wait no longer. In the next two chapters, we'll look at some
+ examples.
+ </para>
+
+ </section>
+
+ </section>
+
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</chapter>
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/master.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,33 +1,33 @@
<?xml version='1.0' encoding="iso-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
<book lang="en">
- <xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <preface>
+ <xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <preface>
<title>Note</title>
<para>
- JSR-299 has recently changed its name from "Web Beans" to "Java
- Contexts and Dependency Injection". The reference guide still refers
- to JSR-299 as "Web Beans" and the JSR-299 Reference Implementation as
- the "Web Beans RI". Other documentation, blogs, forum posts etc. may
- use the new nomenclature, including the new name for the JSR-299
- Reference Implementation - "Web Beans".
+ Shortly before the final draft of JSR-299 was submitted, the specification changed its name from "Web Beans" to
+ "Java Contexts and Dependency Injection for the Java EE platform", abbreviated CDI. For a brief period after
+ the renaming, the reference implementation adopted the name "Web Beans". However, this ended up causing more
+ confusion than it solved and Red Hat decided to change the name of the reference implementation to "Weld". You
+ may still find other documentation, blogs, forum posts, etc. that use the old nomenclature. Please update any
+ references you can. The naming game is over.
</para>
-
+
<para>
- You'll also find that some of the more recent functionality to be
- specified is missing (such as producer fields, realization,
- asynchronous events, XML mapping of EE resources).
+ You'll also find that some of the functionality that once existed in the specification is now missing, such as
+ defining beans in XML. These features will be available as portable extensions for CDI in the Weld project, and
+ perhaps other implementations.
</para>
- </preface>
-
- <toc/>
-
- <part>
- <title>Using contextual objects</title>
+ </preface>
+
+ <toc/>
+
+ <part>
+ <title>Contextual components, loose-coupling and strong typing</title>
<xi:include href="part1.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="intro.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
@@ -36,20 +36,20 @@
<xi:include href="injection.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scopescontexts.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="producermethods.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
-
- <part>
+
+ </part>
+
+ <part>
<title>Developing loosely-coupled code</title>
<xi:include href="part2.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="interceptors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="decorators.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="events.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
-
- <part>
+
+ </part>
+
+ <part>
<title>Making the most of strong typing</title>
<xi:include href="part3.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
@@ -58,33 +58,34 @@
<xi:include href="specialization.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="xml.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- </part>
-
- <part>
- <title>Web Beans and the Java EE ecosystem</title>
+ </part>
+
+ <part>
+ <title>CDI and the Java EE ecosystem</title>
<xi:include href="part4.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ee.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="extend.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ </part>
+
+ <xi:include href="next.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <part>
+ <title>Weld reference</title>
- </part>
-
- <xi:include href="next.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <part>
- <title>Web Beans Reference</title>
-
<xi:include href="part5.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="environments.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="extensions.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="viewlayers.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
+
+ </part>
+
+ <xi:include href="ri-spi.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="ri-spi.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
-
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
</book>
-
Modified: doc/trunk/reference/en-US/part1.xml
===================================================================
--- doc/trunk/reference/en-US/part1.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/part1.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,129 +1,176 @@
-<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<partintro>
-<partintro>
+ <!-- This part could probably be split into a chapter of it's own, perhaps "Overview" with subsection for Concepts
+ and History -->
+
+<!-- this specification defines an SPI that allows alternative, non-platform technologies to integrate
+with the con-
+tainer, for example, alternative web presentation technologies.
+-->
+
+ <!-- NOTE synchronize this intro with the intro on http://seamframework.org/Weld -->
+ <para>
+ The <ulink src="http://jcp.org/en/jsr/detail?id=299">JSR-299</ulink> specification (CDI) defines a set of services
+ for the Java EE environment that make applications much easier to develop. CDI layers an enhanced lifecycle and
+ interaction model over existing Java component types, including Managed Beans (JavaBeans) and Enterprise JavaBeans
+ (EJB session beans). As a complement to the traditional Java EE programming model, the services provide:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ an improved lifecycle for stateful components, bound to well-defined <emphasis>contexts</emphasis>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a typesafe approach to <emphasis>dependency injection</emphasis>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ component interaction via an <emphasis>event notification facility</emphasis>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a better approach to binding <emphasis>interceptors</emphasis> to components, along with a new kind of
+ interceptor, called a <emphasis>decorator</emphasis>, that is more appropriate for use in solving business problems, and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ an <emphasis>SPI</emphasis> for developing portable extensions for the Java EE platform.
+ </para>
+ </listitem>
+ </itemizedlist>
- <para>The Web Beans (JSR-299) specification defines a set of services for
- the Java EE environment that makes applications much easier to develop.
- Web Beans layers an enhanced lifecycle and interaction model over existing
- Java component types including JavaBeans and Enterprise Java Beans. As a
- complement to the traditional Java EE programming model, the Web Beans
- services provide:</para>
+ <para>
+ A component that receives CDI services is referred to, generally, as a bean. The CDI services are a core aspect of
+ the Java EE platform and apply to the following types of components that exist in the platform:
+ </para>
- <itemizedlist>
- <listitem>
- <para>an improved lifecycle for stateful components, bound to well-defined
- <emphasis>contexts</emphasis>,</para>
- </listitem>
- <listitem>
- <para>a typesafe approach to <emphasis>dependency injection</emphasis>,</para>
- </listitem>
- <listitem>
- <para>interaction via an <emphasis>event notification</emphasis> facility,
- and</para>
- </listitem>
- <listitem>
- <para>a better approach to binding <emphasis>interceptors</emphasis> to
- components, along with a new kind of interceptor, called a
- <emphasis>decorator</emphasis>, that is more appropriate for use in
- solving business problems.</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>all Managed Beans (JavaBeans), including JSF managed beans,</para>
+ </listitem>
+ <listitem>
+ <para>all Enterprise JavaBeans (EJBs), and</para>
+ </listitem>
+ <listitem>
+ <para>all Servlets.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ CDI is especially useful in the context of web applications, but is applicable to a wide variety of applications.
+ It may even be used in the Java SE context, in conjunction with an embeddable EJB Lite container, as defined in
+ the EJB 3.1 specification, or through an extension (see <xref linkend="weld-se"/>).
+ </para>
- <para>Dependency injection, together with contextual lifecycle management,
- saves the user of an unfamiliar API from having to ask and answer the following
- questions:</para>
+ <para>
+ The concerns handled by CDI save the user who is unfamiliar with an API from having to answer the following
+ questions:
+ </para>
- <itemizedlist>
- <listitem>
- <para>what is the lifecycle of this object?</para>
- </listitem>
- <listitem>
- <para>how many simultaneous clients can it have?</para>
- </listitem>
- <listitem>
- <para>is it multithreaded?</para>
- </listitem>
- <listitem>
- <para>where can I get one from?</para>
- </listitem>
- <listitem>
- <para>do I need to explicitly destroy it?</para>
- </listitem>
- <listitem>
- <para>where should I keep my reference to it when I'm not
- using it directly?</para>
- </listitem>
- <listitem>
- <para>how can I add an indirection layer, so that the implementation
- of this object can vary at deployment time?</para>
- </listitem>
- <listitem>
- <para>how should I go about sharing this object between other objects?</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>What is the lifecycle of this object?</para>
+ </listitem>
+ <listitem>
+ <para>How many simultaneous clients can it have?</para>
+ </listitem>
+ <listitem>
+ <para>Is it multithreaded?</para>
+ </listitem>
+ <listitem>
+ <para>How do I retrieve it?</para>
+ </listitem>
+ <listitem>
+ <para>Do I need to explicitly destroy it?</para>
+ </listitem>
+ <listitem>
+ <para>
+ Where should I keep the reference to it when I'm not currently using it?
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ How can I define alternatives, so that the implementation of this object can vary at deployment time?
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ How should I go about sharing this object between other objects?
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The main theme of CDI, which is instrumental in removing these complexities, is <emphasis>loose-couping with
+ strong typing</emphasis>. Let's study what that phrase means.
+ </para>
- <para>A Web Bean specifies only the type and semantics of other Web Beans
- it depends upon. It need not be aware of the actual lifecycle, concrete
- implementation, threading model or other clients of any Web Bean it depends
- upon. Even better, the concrete implementation, lifecycle and threading model
- of a Web Bean it depends upon may vary according to the deployment scenario,
- without affecting any client.</para>
+ <para>
+ A bean specifies only the type and semantics of other beans it depends upon. It need not be aware of the actual
+ lifecycle, concrete implementation, threading model or other clients of any bean it depends upon. Even better, the
+ concrete implementation, lifecycle and threading model of a bean it depends upon may vary according to the
+ deployment scenario, without affecting any client. This loose-coupling is what makes this architecture so simple,
+ yet powerful.
+ </para>
- <para>Events, interceptors and decorators enhance the <emphasis>loose-coupling</emphasis>
- that is inherent in this model:</para>
+ <para>
+ Events, interceptors and decorators enhance the <emphasis>loose-coupling</emphasis> inherent in this model:
+ </para>
- <itemizedlist>
- <listitem>
- <para><emphasis>event notifications</emphasis> decouple event producers
- from event consumers,</para>
- </listitem>
- <listitem>
- <para><emphasis>interceptors</emphasis> decouple technical concerns from
- business logic, and</para>
- </listitem>
- <listitem>
- <para><emphasis>decorators</emphasis> allow business concerns to be
- compartmentalized.</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>event notifications</emphasis> decouple event producers from event consumers,</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>interceptors</emphasis> decouple technical concerns from business logic, and</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>decorators</emphasis> allow business concerns to be compartmentalized.</para>
+ </listitem>
+ </itemizedlist>
- <para>Most importantly, Web Beans provides all these facilities in a
- <emphasis>typesafe</emphasis> way. Web Beans never uses string-based
- identifiers to determine how collaborating objects fit together. And
- XML, though it remains an option, is rarely used. Instead, Web Beans
- uses the typing information that is already available in the Java
- object model, together with a new pattern, called
- <emphasis>binding annotations</emphasis>, to wire together Web Beans,
- their dependencies, their interceptors and decorators and their event
- consumers.</para>
+ <para>
+ What's even more powerful (and comforting) is that CDI provides all these facilities in a
+ <emphasis>typesafe</emphasis> way. CDI never relies on string-based identifiers to determine how collaborating
+ objects fit together. (XML is rarely used, reserved only to activate alternatives and define ordering at
+ deployment time). Instead, CDI uses the typing information that is already available in the Java object model,
+ then extends it with a new typing pattern, called <emphasis>qualifier annotations</emphasis>, to wire together
+ beans, their dependencies, their interceptors and decorators and their event consumers.
+ </para>
- <para>The Web Beans services are general and apply to the following types of
- components that exist in the Java EE environment:</para>
+ <para>
+ CDI even provides the necessary integration points, through a comprehensive SPI, so that other kinds of components
+ defined by future Java EE specifications or by non-standard frameworks may be cleanly integrated with CDI, take
+ advantage of the CDI services, and interact with any other kind of platform component.
+ </para>
- <itemizedlist>
- <listitem>
- <para>all JavaBeans,</para>
- </listitem>
- <listitem>
- <para>all EJBs, and</para>
- </listitem>
- <listitem>
- <para>all Servlets.</para>
- </listitem>
- </itemizedlist>
+ <para>
+ CDI was influenced by a number of existing Java frameworks, including Seam, Guice and Spring. However, CDI has its
+ own, very distinct, character: more typesafe than Seam, more stateful and less XML-centric than Spring, more web and
+ enterprise-application capable than Guice. But it couldn't have been any of these without inspiration from the
+ frameworks mentioned and <emphasis>lots</emphasis> of collaboration and hard work by the JSR-299 Expert Group
+ (EG).
+ </para>
- <para>Web Beans even provides the necessary integration points so that other
- kinds of components defined by future Java EE specifications or by non-standard
- frameworks may be cleanly integrated with Web Beans, take advantage of the Web
- Beans services, and interact with any other kind of Web Bean.</para>
+ <para>
+ Finally, JSR-299 is a <ulink src="http://jcp.org">Java Community Process</ulink> (JCP) standard that integrates
+ cleanly with the Java EE platform, and with any Java SE environment where embeddable EJB Lite is available. In
+ fact, Java EE 6 requires that all compliant application servers provide support for JSR-299 (even in the web
+ profile).
+ </para>
- <para>Web Beans was influenced by a number of existing Java frameworks,
- including Seam, Guice and Spring. However, Web Beans has its own very distinct
- character: more typesafe than Seam, more stateful and less XML-centric than
- Spring, more web and enterprise-application capable than Guice.</para>
-
- <para>Most importantly, Web Beans is a JCP standard that integrates
- cleanly with Java EE, and with any Java SE environment where embeddable
- EJB Lite is available.</para>
-
-</partintro>
\ No newline at end of file
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</partintro>
15 years, 1 month