[seam-commits] Seam SVN: r11012 - in modules/trunk: beans and 29 other directories.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Wed May 27 00:22:02 EDT 2009
Author: dan.j.allen
Date: 2009-05-27 00:22:02 -0400 (Wed, 27 May 2009)
New Revision: 11012
Added:
modules/trunk/beans/
modules/trunk/beans/pom.xml
modules/trunk/beans/src/
modules/trunk/beans/src/main/
modules/trunk/beans/src/main/java/
modules/trunk/beans/src/main/java/org/
modules/trunk/beans/src/main/java/org/jboss/
modules/trunk/beans/src/main/java/org/jboss/seam/
modules/trunk/beans/src/main/java/org/jboss/seam/beans/
modules/trunk/beans/src/main/java/org/jboss/seam/beans/Default.java
modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeBeanSelector.java
modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelected.java
modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelectedBean.java
modules/trunk/beans/src/main/resources/
modules/trunk/beans/src/main/resources/META-INF/
modules/trunk/beans/src/main/resources/META-INF/beans.xml
modules/trunk/el/src/main/java/org/jboss/seam/el/ExpressionsProducer.java
modules/trunk/el/src/test/java/org/jboss/seam/el/ExpressionsProducerTest.java
modules/trunk/el/src/test/resources/org/
modules/trunk/el/src/test/resources/org/jboss/
modules/trunk/el/src/test/resources/org/jboss/testharness/
modules/trunk/el/src/test/resources/org/jboss/testharness/impl/
modules/trunk/el/src/test/resources/org/jboss/testharness/impl/packaging/
modules/trunk/el/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/
modules/trunk/el/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/default/
modules/trunk/el/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/default/beans.xml
modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesMessages.java
modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesMessagesTest.java
modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessagesWrapper.java
Removed:
modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesStatusMessages.java
modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesStatusMessagesTest.java
modules/trunk/faces/src/test/resources/org/jboss/seam/
Modified:
modules/trunk/el/
modules/trunk/el/pom.xml
modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java
modules/trunk/faces/pom.xml
modules/trunk/faces/src/main/java/org/jboss/seam/faces/Faces.java
modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesExpressions.java
modules/trunk/faces/src/main/java/org/jboss/seam/faces/application/SeamViewHandler.java
modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesExpressionsTest.java
modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessages.java
modules/trunk/international/src/test/java/org/jboss/seam/international/InterpolatorTest.java
modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesTest.java
modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesUnitTest.java
modules/trunk/parent/pom.xml
modules/trunk/version-matrix/pom.xml
Log:
implement runtime selection of Expressions type
use a delegation-based specialization strategy for StatusMessages
Property changes on: modules/trunk/beans
___________________________________________________________________
Name: svn:ignore
+ target
.classpath
.project
.settings
Added: modules/trunk/beans/pom.xml
===================================================================
--- modules/trunk/beans/pom.xml (rev 0)
+++ modules/trunk/beans/pom.xml 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,53 @@
+<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>
+ <artifactId>seam-parent</artifactId>
+ <groupId>org.jboss.seam</groupId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>seam-beans</artifactId>
+ <packaging>jar</packaging>
+ <version>3.0.0-SNAPSHOT</version>
+ <name>Seam Beans Module</name>
+ <description>A support module for performing bean resolution, such as runtime selection of a bean based on active framework.</description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${webbeans.groupId}</groupId>
+ <artifactId>jsr299-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${webbeans.groupId}</groupId>
+ <artifactId>webbeans-logging</artifactId>
+ <!-- assumes use of Web Beans impl -->
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <!--
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <suiteXmlFiles>
+ <suiteXmlFile>src/test/resources/unit-test-suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ </configuration>
+ </plugin>
+ -->
+
+ </plugins>
+ </build>
+
+</project>
Added: modules/trunk/beans/src/main/java/org/jboss/seam/beans/Default.java
===================================================================
--- modules/trunk/beans/src/main/java/org/jboss/seam/beans/Default.java (rev 0)
+++ modules/trunk/beans/src/main/java/org/jboss/seam/beans/Default.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,31 @@
+package org.jboss.seam.beans;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.enterprise.inject.BindingType;
+
+/**
+ * A binding type for the default implementation. This binding
+ * type is placed on the default implementation and a producer
+ * is responsible for selecting this type in the case that
+ * no other types are defined. Note that this binding type
+ * is not inherited, since it should resolve to exactly
+ * one bean and thus explicitly stated.
+ *
+ * @author Dan Allen
+ */
+ at Target( { TYPE, METHOD, PARAMETER, FIELD })
+ at Retention(RUNTIME)
+ at Documented
+ at BindingType
+public @interface Default
+{
+}
Added: modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeBeanSelector.java
===================================================================
--- modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeBeanSelector.java (rev 0)
+++ modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeBeanSelector.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,72 @@
+package org.jboss.seam.beans;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.enterprise.inject.AmbiguousResolutionException;
+import javax.enterprise.inject.AnnotationLiteral;
+import javax.enterprise.inject.Initializer;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+
+public
+abstract
+class RuntimeBeanSelector<T>
+{
+ private BeanManager manager;
+
+ private T defaultInstance;
+
+ private List<T> instances = new ArrayList<T>();
+
+ public RuntimeBeanSelector() {}
+
+ public @Initializer
+ RuntimeBeanSelector(BeanManager manager)
+ {
+ this.manager = manager;
+ registerImplementations();
+ }
+
+ public abstract Class<T> getType();
+
+ public T selectImplementation()
+ {
+ List<T> selected = new ArrayList<T>();
+ for (T candidate : instances)
+ {
+ if (((RuntimeSelectedBean) candidate).isActive())
+ {
+ selected.add(candidate);
+ }
+ }
+
+ if (selected.size() == 0)
+ {
+ return defaultInstance;
+ }
+ else if (selected.size() == 1)
+ {
+ return selected.iterator().next();
+ }
+ else
+ {
+ throw new AmbiguousResolutionException("Too many instances active for type " + getType().getTypeParameters()[0]);
+ }
+ }
+
+ protected void registerImplementations()
+ {
+ defaultInstance = manager.getInstanceByType(getType(), new AnnotationLiteral<Default>() {});
+
+ Set<Bean<T>> implementations = manager.getBeans(getType(), new AnnotationLiteral<RuntimeSelected>() {});
+ for (Bean<T> candidate : implementations)
+ {
+ if (candidate.getTypes().contains(RuntimeSelectedBean.class))
+ {
+ instances.add(manager.getInstance(candidate));
+ }
+ }
+ }
+}
Added: modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelected.java
===================================================================
--- modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelected.java (rev 0)
+++ modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelected.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,28 @@
+package org.jboss.seam.beans;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.enterprise.inject.BindingType;
+
+/**
+ * A binding type which marks one of any number of
+ * bean implementations that can be selected at
+ * runtime. The first bean which indicates that
+ * it is active is selected.
+ *
+ * @author Dan Allen
+ */
+ at Target( { TYPE, METHOD, FIELD })
+ at Retention(RUNTIME)
+ at Documented
+ at BindingType
+public @interface RuntimeSelected
+{
+}
Added: modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelectedBean.java
===================================================================
--- modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelectedBean.java (rev 0)
+++ modules/trunk/beans/src/main/java/org/jboss/seam/beans/RuntimeSelectedBean.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,21 @@
+package org.jboss.seam.beans;
+
+/**
+ * An interface which indicates that the instance of this bean class that is
+ * appropriate for the current thread is selected at runtime. This allows
+ * for an implementation to be matched with the framework serving the
+ * request (e.g., JSF, Wicket, etc).
+ *
+ * @author Dan Allen
+ */
+public interface RuntimeSelectedBean
+{
+ /**
+ * Report whether this implementation is active for the current thread. If
+ * the implementation is annotated with @Default and no other implementation
+ * is active, this instance will still be selected.
+ *
+ * @return Whether the implementation is active for the current thread
+ */
+ public boolean isActive();
+}
Added: modules/trunk/beans/src/main/resources/META-INF/beans.xml
===================================================================
Property changes on: modules/trunk/el
___________________________________________________________________
Name: svn:ignore
- .classpath
.project
.settings
nb-configuration.xml
target
+ .classpath
.project
.settings
attic
nb-configuration.xml
target
temp-testng-customsuite.xml
test-output
Modified: modules/trunk/el/pom.xml
===================================================================
--- modules/trunk/el/pom.xml 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/el/pom.xml 2009-05-27 04:22:02 UTC (rev 11012)
@@ -59,6 +59,11 @@
<artifactId>jboss-el</artifactId>
</dependency>
+ <dependency>
+ <groupId>${seam.groupId}</groupId>
+ <artifactId>seam-beans</artifactId>
+ </dependency>
+
</dependencies>
</project>
Modified: modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/Expressions.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -27,8 +27,9 @@
import javax.el.ELContext;
import javax.el.ExpressionFactory;
-import javax.enterprise.context.ApplicationScoped;
+import org.jboss.seam.beans.Default;
+
/**
* Factory for EL method and value expressions.
*
@@ -37,7 +38,7 @@
* @author Gavin King
*/
public
- at ApplicationScoped
+ at Default
class Expressions implements Serializable
{
private static final long serialVersionUID = 7420955152664486125L;
@@ -49,13 +50,14 @@
{
return SeamExpressionFactory.INSTANCE;
}
-
+
/**
- * Get an appropriate ELContext. If there is an active JSF request,
- * use JSF's ELContext. Otherwise, use one that we create.
+ * Get an appropriate ELContext. If there is an active JSF request, use JSF's
+ * ELContext. Otherwise, use one that we create.
*/
- public ELContext getELContext() {
- return SeamEL.createELContext();
+ public ELContext getELContext()
+ {
+ return SeamEL.createELContext();
}
/**
@@ -67,7 +69,7 @@
{
return createValueExpression(expression, Object.class);
}
-
+
/**
* Create a method expression.
*
@@ -77,9 +79,10 @@
{
return createMethodExpression(expression, Object.class);
}
-
+
/**
- * Get the value of a unified ValueExpression, coercing it to the expected type.
+ * Get the value of a unified ValueExpression, coercing it to the expected
+ * type.
*
* @param expression a unified ValueExpression
* @param type the expected value type
@@ -91,7 +94,7 @@
{
return (T) expression.getValue(getELContext());
}
-
+
/**
* Inspect the unified ValueExpression and return the value's expected type.
*
@@ -114,22 +117,24 @@
{
expression.setValue(getELContext(), value);
}
-
+
/**
- * Invoke the unified MethodExpression, coercing the result to the expected return type.
+ * Invoke the unified MethodExpression, coercing the result to the expected
+ * return type.
*
* @param expression a unified MethodExpression
* @param returnType the expected return type
* @param args method arguments
*
- * @return the return value of the underlying method represented by the unified MethodExpression
+ * @return the return value of the underlying method represented by the
+ * unified MethodExpression
*/
@SuppressWarnings("unchecked")
public <T> T invoke(javax.el.MethodExpression expression, Class<T> returnType, Object... args)
{
return (T) expression.invoke(getELContext(), args);
}
-
+
/**
* Create a value expression.
*
@@ -138,63 +143,51 @@
*/
public <T> ValueExpression<T> createValueExpression(final String expression, final Class<T> type)
{
-
+
return new ValueExpression<T>()
{
- private javax.el.ValueExpression facesValueExpression;
- private javax.el.ValueExpression seamValueExpression;
-
+ private javax.el.ValueExpression unifiedValueExpression;
+
public javax.el.ValueExpression toUnifiedValueExpression()
{
- if ( isFacesContextActive() )
+ if (unifiedValueExpression == null)
{
- if (facesValueExpression==null)
- {
- facesValueExpression = createExpression();
- }
- return facesValueExpression;
+ unifiedValueExpression = createExpression();
}
- else
- {
- if (seamValueExpression==null)
- {
- seamValueExpression = createExpression();
- }
- return seamValueExpression;
- }
+ return unifiedValueExpression;
}
-
+
private javax.el.ValueExpression createExpression()
{
- return getExpressionFactory().createValueExpression( getELContext(), expression, type );
+ return getExpressionFactory().createValueExpression(getELContext(), expression, type);
}
-
+
@SuppressWarnings("unchecked")
public T getValue()
{
- return (T) toUnifiedValueExpression().getValue( getELContext() );
+ return (T) toUnifiedValueExpression().getValue(getELContext());
}
- public void setValue(T value)
+ public void setValue(T value)
{
- toUnifiedValueExpression().setValue( getELContext(), value );
+ toUnifiedValueExpression().setValue(getELContext(), value);
}
-
+
public String getExpressionString()
{
return expression;
}
-
+
@SuppressWarnings("unchecked")
public Class<T> getType()
{
// QUESTION shouldn't we use the type provided in the constructor?
- return toUnifiedValueExpression().getType( getELContext() );
+ return toUnifiedValueExpression().getType(getELContext());
}
-
+
};
}
-
+
/**
* Create a method expression.
*
@@ -202,94 +195,83 @@
* @param type the method return type
* @param argTypes the method parameter types
*/
- public <T> MethodExpression<T> createMethodExpression(final String expression, final Class<T> type, final Class... argTypes)
+ public <T> MethodExpression<T> createMethodExpression(final String expression, final Class<T> type, final Class<?>... argTypes)
{
return new MethodExpression<T>()
{
- private javax.el.MethodExpression facesMethodExpression;
- private javax.el.MethodExpression seamMethodExpression;
-
+ private javax.el.MethodExpression unifiedMethodExpression;
+
public javax.el.MethodExpression toUnifiedMethodExpression()
{
- if ( isFacesContextActive() )
+ if (unifiedMethodExpression == null)
{
- if (facesMethodExpression==null)
- {
- facesMethodExpression = createExpression();
- }
- return facesMethodExpression;
+ unifiedMethodExpression = createExpression();
}
- else
- {
- if (seamMethodExpression==null)
- {
- seamMethodExpression = createExpression();
- }
- return seamMethodExpression;
- }
+ return unifiedMethodExpression;
}
-
+
private javax.el.MethodExpression createExpression()
{
- return getExpressionFactory().createMethodExpression( getELContext(), expression, type, argTypes );
+ return getExpressionFactory().createMethodExpression(getELContext(), expression, type, argTypes);
}
-
+
+ @SuppressWarnings("unchecked")
public T invoke(Object... args)
{
- return (T) toUnifiedMethodExpression().invoke( getELContext(), args );
+ return (T) toUnifiedMethodExpression().invoke(getELContext(), args);
}
-
+
public String getExpressionString()
{
return expression;
}
-
+
};
}
-
+
/**
- * A value expression - an EL expression that evaluates to
- * an attribute getter or get/set pair. This interface
- * is just a genericized version of the Unified EL ValueExpression
- * interface.
+ * A value expression - an EL expression that evaluates to an attribute
+ * getter or get/set pair. This interface is just a genericized version of
+ * the Unified EL ValueExpression interface.
*
* @author Gavin King
- *
+ *
* @param <T> the type of the value
*/
public static interface ValueExpression<T> extends Serializable
{
public T getValue();
+
public void setValue(T value);
+
public String getExpressionString();
+
public Class<T> getType();
+
/**
* @return the underlying Unified EL ValueExpression
*/
public javax.el.ValueExpression toUnifiedValueExpression();
}
-
+
/**
- * A method expression - an EL expression that evaluates to
- * a method. This interface is just a genericized version of
- * the Unified EL ValueExpression interface.
+ * A method expression - an EL expression that evaluates to a method. This
+ * interface is just a genericized version of the Unified EL ValueExpression
+ * interface.
*
* @author Gavin King
- *
+ *
* @param <T> the method return type
*/
public static interface MethodExpression<T> extends Serializable
{
public T invoke(Object... args);
+
public String getExpressionString();
+
/**
* @return the underlying Unified EL MethodExpression
*/
public javax.el.MethodExpression toUnifiedMethodExpression();
}
-
- protected boolean isFacesContextActive()
- {
- return false;
- }
}
Added: modules/trunk/el/src/main/java/org/jboss/seam/el/ExpressionsProducer.java
===================================================================
--- modules/trunk/el/src/main/java/org/jboss/seam/el/ExpressionsProducer.java (rev 0)
+++ modules/trunk/el/src/main/java/org/jboss/seam/el/ExpressionsProducer.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,35 @@
+package org.jboss.seam.el;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Initializer;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.jboss.seam.beans.RuntimeBeanSelector;
+
+public
+ at ApplicationScoped
+class ExpressionsProducer extends RuntimeBeanSelector<Expressions>
+{
+ ExpressionsProducer() {}
+
+ public @Initializer ExpressionsProducer(BeanManager manager)
+ {
+ super(manager);
+ }
+
+ @Override
+ public Class<Expressions> getType()
+ {
+ return Expressions.class;
+ }
+
+ @Override
+ public
+ @Produces
+ Expressions selectImplementation()
+ {
+ return super.selectImplementation();
+ }
+
+}
Added: modules/trunk/el/src/test/java/org/jboss/seam/el/ExpressionsProducerTest.java
===================================================================
--- modules/trunk/el/src/test/java/org/jboss/seam/el/ExpressionsProducerTest.java (rev 0)
+++ modules/trunk/el/src/test/java/org/jboss/seam/el/ExpressionsProducerTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,20 @@
+package org.jboss.seam.el;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertSame;
+
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.webbeans.test.AbstractWebBeansTest;
+import org.testng.annotations.Test;
+
+ at Artifact
+public class ExpressionsProducerTest extends AbstractWebBeansTest
+{
+ @Test
+ public void testExpressionsProducer()
+ {
+ Expressions expressions = getCurrentManager().getInstanceByType(Expressions.class);
+ assertNotNull(expressions);
+ assertSame(expressions.getClass(), Expressions.class);
+ }
+}
Added: modules/trunk/el/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/default/beans.xml
===================================================================
Modified: modules/trunk/faces/pom.xml
===================================================================
--- modules/trunk/faces/pom.xml 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/pom.xml 2009-05-27 04:22:02 UTC (rev 11012)
@@ -42,7 +42,7 @@
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
- <scope>test</scope>
+ <scope>provided</scope>
</dependency>
<dependency>
Modified: modules/trunk/faces/src/main/java/org/jboss/seam/faces/Faces.java
===================================================================
--- modules/trunk/faces/src/main/java/org/jboss/seam/faces/Faces.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/src/main/java/org/jboss/seam/faces/Faces.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,28 +1,28 @@
-package org.jboss.seam.faces;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import javax.enterprise.inject.deployment.DeploymentType;
-
-/**
- * A binding type used on a JSF-specific implementation
- * that specializes Seam's standard implementation.
- *
- * @author Dan Allen
- */
- at Target( { TYPE, METHOD, PARAMETER, FIELD })
- at Retention(RUNTIME)
- at Documented
- at DeploymentType
- at Inherited
-public @interface Faces {
-}
+package org.jboss.seam.faces;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.enterprise.inject.BindingType;
+
+/**
+ * Binding type for JSF-specific beans.
+ *
+ * @author Dan Allen
+ */
+ at Target( { TYPE, METHOD, PARAMETER, FIELD })
+ at Retention(RUNTIME)
+ at Documented
+ at BindingType
+ at Inherited
+public @interface Faces
+{
+}
Modified: modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesExpressions.java
===================================================================
--- modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesExpressions.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesExpressions.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -2,37 +2,34 @@
package org.jboss.seam.faces;
import javax.el.ELContext;
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.inject.deployment.Specializes;
import javax.faces.context.FacesContext;
+import org.jboss.seam.beans.RuntimeSelected;
+import org.jboss.seam.beans.RuntimeSelectedBean;
import org.jboss.seam.el.Expressions;
/**
* Factory for method and value bindings in a JSF environment.
*
* @author Gavin King
+ * @author Dan Allen
*/
public
- at Faces
- at Specializes
- at ApplicationScoped
-class FacesExpressions extends Expressions
+ at RuntimeSelected
+class FacesExpressions extends Expressions implements RuntimeSelectedBean
{
+ public boolean isActive()
+ {
+ return FacesContext.getCurrentInstance() != null && FacesContext.getCurrentInstance().getCurrentPhaseId() != null;
+ }
+
/**
- * Get an appropriate ELContext. If there is an active JSF request,
- * use JSF's ELContext. Otherwise, use one that we created.
+ * @return the JSF ELContext
*/
@Override
public ELContext getELContext()
{
- return isFacesContextActive() ? FacesContext.getCurrentInstance().getELContext() : super.getELContext();
+ return FacesContext.getCurrentInstance().getELContext();
}
-
- @Override
- protected boolean isFacesContextActive()
- {
- return FacesContext.getCurrentInstance() != null && FacesContext.getCurrentInstance().getCurrentPhaseId() != null;
- }
}
\ No newline at end of file
Added: modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesMessages.java
===================================================================
--- modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesMessages.java (rev 0)
+++ modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesMessages.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,238 @@
+package org.jboss.seam.faces;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.enterprise.inject.Initializer;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+import org.jboss.seam.international.StatusMessage;
+import org.jboss.seam.international.StatusMessages;
+import org.jboss.seam.international.StatusMessagesWrapper;
+import org.jboss.webbeans.log.LogProvider;
+import org.jboss.webbeans.log.Logging;
+
+/**
+ * <p>
+ * A bean which wraps the generic StatusMessages component to provide support
+ * for JSF. The StatusMessage objects are translated to JSF FacesMessage objects
+ * and registered with the FacesContext by this class prior to view rendering or
+ * a servlet redirect.
+ * </p>
+ *
+ * <p>
+ * To access the JSF FacesMessage objects once they have been registered with
+ * the FacesContext, you should use the methods getMessageList() and
+ * getMessagesList(String), which were added to FacesContext in JSF 2.0.
+ * </p>
+ *
+ * <p>
+ * For instance, to retrieve the list of global messages, you can use the
+ * following value expression in your page:
+ * </p>
+ *
+ * <pre>
+ * #{facesContext.getMessageList(null)}
+ * </pre>
+ *
+ * <p>
+ * To retrieve the list of messages for a "client id", you can use this
+ * expression:
+ * </p>
+ *
+ * <pre>
+ * #{facesContext.getMessageList('username')}
+ * </pre>
+ *
+ * <p>
+ * These examples rely, of course, on the JBoss EL.
+ * </p>
+ *
+ * @author Gavin King
+ * @author Pete Muir
+ * @author Dan Allen
+ */
+public
+ at Faces
+class FacesMessages extends StatusMessagesWrapper
+{
+ private static final LogProvider log = Logging.getLogProvider(FacesMessages.class);
+
+ private StatusMessages statusMessages;
+
+ public
+ @Initializer
+ FacesMessages(StatusMessages statusMessages)
+ {
+ this.statusMessages = statusMessages;
+ }
+
+ @Override
+ public StatusMessages getStatusMessages()
+ {
+ return this.statusMessages;
+ }
+
+ /**
+ * A convenience method to convert a FacesMessage into a StatusMessage and
+ * register it as a global message. It may be that the application receives a
+ * FacesMessage object from some part of the system and needs to join it with
+ * the current set of StatusMessage objects.
+ *
+ * @param message A populated JSF FacesMessage object
+ */
+ public void add(FacesMessage message)
+ {
+ add(toSeverity(message.getSeverity()), null, null, message.getSummary(), message.getDetail());
+ }
+
+ /**
+ * A convenience method to convert a FacesMessage into a StatusMessage and
+ * register it with a control. It may be that the application receives a
+ * FacesMessage object from some part of the system and needs to join it with
+ * the current set of StatusMessage objects.
+ *
+ * @param id The client id of the target component
+ * @param message A populated JSF FacesMessage object
+ */
+ public void addToControl(String id, FacesMessage message)
+ {
+ addToControl(id, toSeverity(message.getSeverity()), null, null, message.getSummary(), message.getDetail());
+ }
+
+ /**
+ * Called by a JSF SystemEventListener listening for the PreRenderViewEvent
+ * to transpose Seam status messages to real JSF messages and register them
+ * with the FacesContext.
+ */
+ @Override
+ public void onBeforeRender()
+ {
+ getStatusMessages().onBeforeRender();
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ for (StatusMessage statusMessage : getGlobalMessages())
+ {
+ facesContext.addMessage(null, toFacesMessage(statusMessage));
+ }
+ for (Map.Entry<String, List<StatusMessage>> messagesForKey : getKeyedMessages().entrySet())
+ {
+ String clientId = getClientId(messagesForKey.getKey(), facesContext);
+ if (clientId == null)
+ {
+ log.warn("Could not locate control '" + messagesForKey.getKey() + "' when registering JSF message. A global message will be created as a fallback.");
+ }
+ for (StatusMessage statusMessage : messagesForKey.getValue())
+ {
+ facesContext.addMessage(clientId, toFacesMessage(statusMessage));
+ }
+ }
+ clear();
+ }
+
+ /**
+ * Convert a StatusMessage to a FacesMessage
+ */
+ private FacesMessage toFacesMessage(StatusMessage statusMessage)
+ {
+ if (statusMessage.getSummary() != null && statusMessage.getSummary().length() > 0)
+ {
+ return new FacesMessage(toFacesSeverity(statusMessage.getSeverity()), statusMessage.getSummary(), statusMessage.getDetail());
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Convert a FacesMessage.Severity to a StatusMessage.Severity
+ */
+ private static StatusMessage.Severity toSeverity(FacesMessage.Severity severity)
+ {
+ if (FacesMessage.SEVERITY_ERROR.equals(severity))
+ {
+ return StatusMessage.Severity.ERROR;
+ }
+ else if (FacesMessage.SEVERITY_FATAL.equals(severity))
+ {
+ return StatusMessage.Severity.FATAL;
+ }
+ else if (FacesMessage.SEVERITY_WARN.equals(severity))
+ {
+ return StatusMessage.Severity.WARN;
+ }
+ else
+ {
+ return StatusMessage.Severity.INFO;
+ }
+ }
+
+ /**
+ * Convert a StatusMessage.Severity to a FacesMessage.Severity
+ */
+ private FacesMessage.Severity toFacesSeverity(StatusMessage.Severity severity)
+ {
+ switch (severity)
+ {
+ case ERROR:
+ return FacesMessage.SEVERITY_ERROR;
+ case FATAL:
+ return FacesMessage.SEVERITY_FATAL;
+ case WARN:
+ return FacesMessage.SEVERITY_WARN;
+ case INFO:
+ default:
+ return FacesMessage.SEVERITY_INFO;
+ }
+ }
+
+ /**
+ * Calculate the JSF client ID from the provided widget ID.
+ * TODO It would be great if this could do suffix maching.
+ */
+ private String getClientId(String targetId, FacesContext facesContext)
+ {
+ if (isAbsoluteClientIdPresent(targetId, facesContext))
+ {
+ return targetId;
+ }
+ else
+ {
+ return getClientId(facesContext.getViewRoot(), targetId, facesContext);
+ }
+ }
+
+ /**
+ * FIXME does not work if element is inside of form with prependId="false"
+ */
+ private boolean isAbsoluteClientIdPresent(String targetId, FacesContext facesContext)
+ {
+ return facesContext.getViewRoot().findComponent(targetId) != null;
+ }
+
+ private String getClientId(UIComponent component, String targetLocalId, FacesContext facesContext)
+ {
+ String currentLocalId = component.getId();
+ if (currentLocalId != null && currentLocalId.equals(targetLocalId))
+ {
+ return component.getClientId(facesContext);
+ }
+ else
+ {
+ Iterator<UIComponent> iter = component.getFacetsAndChildren();
+ while (iter.hasNext())
+ {
+ String clientId = getClientId(iter.next(), targetLocalId, facesContext);
+ if (clientId != null)
+ {
+ return clientId;
+ }
+ }
+ return null;
+ }
+ }
+
+}
Deleted: modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesStatusMessages.java
===================================================================
--- modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesStatusMessages.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/src/main/java/org/jboss/seam/faces/FacesStatusMessages.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,173 +0,0 @@
-package org.jboss.seam.faces;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.enterprise.context.ConversationScoped;
-import javax.enterprise.inject.Initializer;
-import javax.enterprise.inject.deployment.Specializes;
-import javax.faces.application.FacesMessage;
-import javax.faces.component.UIComponent;
-import javax.faces.context.FacesContext;
-
-import org.jboss.seam.international.Interpolator;
-import org.jboss.seam.international.StatusMessage;
-import org.jboss.seam.international.StatusMessages;
-import org.jboss.webbeans.log.LogProvider;
-import org.jboss.webbeans.log.Logging;
-
-/**
- * <p>A bean which specializes StatusMessage to provide support for
- * JSF. Generic StatusMessage objects are translated into JSF
- * FacesMessage objects just prior to when the view is rendered.</p>
- *
- * <p>To access the JSF FacesMessage objects once they have been registered
- * with the FacesContext, you should use the methods getMessageList()
- * and getMessagesList(String), which were added to FacesContext in JSF 2.0.</p>
- *
- * <p>For instance, to retrieve the list of global messages, you can use
- * the following value expression in your page:</p>
- *
- * <pre>#{facesContext.getMessageList(null)}</pre>
- *
- * <p>To retrieve the list of messages for a "client id", you can use this
- * expression:</p>
- *
- * <pre>#{facesContext.getMessageList('username')}</pre>
- *
- * <p>These examples rely, of course, on the JBoss EL.</p>
- *
- * QUESTION: should we set Flash#setKeepMessages(boolean)?
- *
- * @author Gavin King
- * @author Pete Muir
- */
-public
- at Faces
- at Specializes
- at ConversationScoped
-class FacesStatusMessages extends StatusMessages
-{
- private static final LogProvider log = Logging.getLogProvider(FacesStatusMessages.class);
-
- public FacesStatusMessages()
- {
- super();
- }
-
- public @Initializer FacesStatusMessages(Interpolator interpolator)
- {
- super(interpolator);
- }
-
- /**
- * Called by a JSF SystemEventListener listening for the PreRenderViewEvent
- * to transpose Seam status messages to real JSF messages and register them
- * with the FacesContext.
- */
- @Override
- public void onBeforeRender()
- {
- super.onBeforeRender();
- FacesContext facesContext = FacesContext.getCurrentInstance();
- for (StatusMessage statusMessage : getGlobalMessages())
- {
- facesContext.addMessage(null, toFacesMessage(statusMessage));
- }
- for (Map.Entry<String, List<StatusMessage>> messagesForKey : getKeyedMessages().entrySet())
- {
- String clientId = getClientId(messagesForKey.getKey(), facesContext);
- if (clientId == null)
- {
- log.warn("Could not locate control '" + messagesForKey.getKey() + "' when registering JSF message. A global message will be created as a fallback.");
- }
- for (StatusMessage statusMessage : messagesForKey.getValue())
- {
- facesContext.addMessage(clientId, toFacesMessage(statusMessage));
- }
- }
- clear();
- }
-
- /**
- * Convert a StatusMessage to a FacesMessage
- */
- private FacesMessage toFacesMessage(StatusMessage statusMessage)
- {
- if (statusMessage.getSummary() != null && statusMessage.getSummary().length() > 0)
- {
- return new FacesMessage(toFacesSeverity(statusMessage.getSeverity()), statusMessage.getSummary(), statusMessage.getDetail());
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Convert a StatusMessage.Severity to a FacesMessage.Severity
- */
- private javax.faces.application.FacesMessage.Severity toFacesSeverity(org.jboss.seam.international.StatusMessage.Severity severity)
- {
- switch (severity)
- {
- case ERROR:
- return FacesMessage.SEVERITY_ERROR;
- case FATAL:
- return FacesMessage.SEVERITY_FATAL;
- case WARN:
- return FacesMessage.SEVERITY_WARN;
- case INFO:
- default:
- return FacesMessage.SEVERITY_INFO;
- }
- }
-
- /**
- * Calculate the JSF client ID from the provided widget ID.
- * TODO It would be great if this could do suffix maching.
- */
- private String getClientId(String targetId, FacesContext facesContext)
- {
- if (isAbsoluteClientIdPresent(targetId, facesContext))
- {
- return targetId;
- }
- else
- {
- return getClientId(facesContext.getViewRoot(), targetId, facesContext);
- }
- }
-
- /**
- * FIXME does not work if element is inside of form with prependId="false"
- */
- private boolean isAbsoluteClientIdPresent(String targetId, FacesContext facesContext)
- {
- return facesContext.getViewRoot().findComponent(targetId) != null;
- }
-
- private String getClientId(UIComponent component, String targetLocalId, FacesContext facesContext)
- {
- String currentLocalId = component.getId();
- if (currentLocalId != null && currentLocalId.equals(targetLocalId))
- {
- return component.getClientId(facesContext);
- }
- else
- {
- Iterator iter = component.getFacetsAndChildren();
- while (iter.hasNext())
- {
- UIComponent child = (UIComponent) iter.next();
- String clientId = getClientId(child, targetLocalId, facesContext);
- if (clientId != null)
- {
- return clientId;
- }
- }
- return null;
- }
- }
-}
Modified: modules/trunk/faces/src/main/java/org/jboss/seam/faces/application/SeamViewHandler.java
===================================================================
--- modules/trunk/faces/src/main/java/org/jboss/seam/faces/application/SeamViewHandler.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/src/main/java/org/jboss/seam/faces/application/SeamViewHandler.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -5,7 +5,7 @@
import javax.faces.application.ViewHandler;
import javax.faces.application.ViewHandlerWrapper;
import javax.faces.context.FacesContext;
-import org.jboss.seam.faces.lifecycle.TransferStatusMessagesListener;
+import org.jboss.seam.faces.lifecycle.ConvertStatusMessagesListener;
/**
* Wrap the standard JSF view handler to capture the
@@ -43,7 +43,7 @@
if (context.getExternalContext().getSession(false) != null)
{
// QUESTION hmmm, we have to convert to faces messages now to leverage JSF's flash feature...I suppose that is okay
- new TransferStatusMessagesListener().execute();
+ new ConvertStatusMessagesListener().execute();
// should I move this next step into TransferStatusMessagesListener?
if (context.getMessages().hasNext())
{
Modified: modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesExpressionsTest.java
===================================================================
--- modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesExpressionsTest.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesExpressionsTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,17 +1,18 @@
package org.jboss.seam.faces;
-import static org.testng.Assert.*;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
import javax.el.CompositeELResolver;
-
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
+
import org.jboss.seam.el.Expressions;
+import org.jboss.seam.el.ExpressionsProducer;
import org.jboss.seam.el.SeamEL;
import org.jboss.seam.mock.faces.MockFacesContext;
import org.jboss.testharness.impl.packaging.Artifact;
import org.jboss.testharness.impl.packaging.Classes;
-import org.jboss.testharness.impl.packaging.jsr299.BeansXml;
import org.jboss.webbeans.test.AbstractWebBeansTest;
import org.testng.annotations.Test;
@@ -23,10 +24,9 @@
* @author Dan Allen
*/
@Artifact(addCurrentPackage = false)
- at BeansXml("beans.xml")
@Classes(
{
- FacesExpressions.class, Expressions.class
+ FacesExpressions.class, Expressions.class, ExpressionsProducer.class
})
public class FacesExpressionsTest extends AbstractWebBeansTest
{
@@ -40,16 +40,16 @@
@Test
public void testUsesELFromFacesContext()
{
- Expressions expressions = getExpressionInstance();
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
+ Expressions expressions = getExpressionInstance();
assertSame(expressions.getELContext(), facesContext.getELContext());
}
private Expressions getExpressionInstance()
{
Expressions expressions = getCurrentManager().getInstanceByType(Expressions.class);
- assert expressions instanceof FacesExpressions;
+ assertTrue(expressions instanceof FacesExpressions);
return expressions;
}
Copied: modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesMessagesTest.java (from rev 10994, modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesStatusMessagesTest.java)
===================================================================
--- modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesMessagesTest.java (rev 0)
+++ modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesMessagesTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,152 @@
+package org.jboss.seam.faces;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertSame;
+
+import java.util.List;
+
+import javax.enterprise.inject.AnnotationLiteral;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+
+import org.jboss.seam.el.Expressions;
+import org.jboss.seam.el.ExpressionsProducer;
+import org.jboss.seam.international.Interpolator;
+import org.jboss.seam.international.LocaleProducer;
+import org.jboss.seam.international.StatusMessage;
+import org.jboss.seam.international.StatusMessages;
+import org.jboss.seam.mock.faces.MockApplication;
+import org.jboss.seam.mock.faces.MockFacesContext;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.jboss.webbeans.context.ConversationContext;
+import org.jboss.webbeans.context.api.helpers.ConcurrentHashMapBeanStore;
+import org.jboss.webbeans.test.AbstractWebBeansTest;
+import org.testng.annotations.Test;
+
+/**
+ * First and foremost, ensure that FacesMessage is configured properly to wrap
+ * the StatusMessages component. Once loaded, verify that FacesMessages adds the
+ * appropriate JSF-specific functionality to the conversation-scoped
+ * StatusMessages repository.
+ *
+ * @author Dan Allen
+ *
+ * @see FacesMessages
+ * @see StatusMessages
+ */
+ at Artifact(addCurrentPackage = false)
+ at Classes(
+{
+ FacesMessages.class, StatusMessages.class, Interpolator.class, Expressions.class, ExpressionsProducer.class, LocaleProducer.class
+})
+public class FacesMessagesTest extends AbstractWebBeansTest
+{
+ @Override
+ public void beforeMethod()
+ {
+ super.beforeMethod();
+ activateConversationContext();
+ installMockFacesContext();
+ }
+
+ /**
+ * Test that the StatusMessage objects properly tranfer to FacesMessage objects
+ * upon the call to FacesMessages#onBeforeRender().
+ */
+ @Test
+ public void testGlobalStatusMessagesGetTransferedToFacesMessages()
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
+ StatusMessages statusMessages = getStatusMessagesInstance();
+
+ statusMessages.add("You've booked a night at {0}. Bon chance!", "Mandalay Bay");
+
+ assertEquals(statusMessages.getGlobalMessages().size(), 1);
+ assertEquals(facesContext.getMessageList().size(), 0);
+
+ facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
+ statusMessages.onBeforeRender();
+
+ assertEquals(statusMessages.getGlobalMessages().size(), 0);
+ assertEquals(facesContext.getMessageList().size(), 1);
+ assertEquals(facesContext.getMessageList(null).size(), 1);
+ FacesMessage facesMessage = facesContext.getMessageList().get(0);
+ assertEquals(facesMessage.getSeverity(), FacesMessage.SEVERITY_INFO);
+ assertEquals(facesMessage.getSummary(), "You've booked a night at Mandalay Bay. Bon chance!");
+ // NOTE this assignment happens inside the FacesMessage implementation
+ assertEquals(facesMessage.getSummary(), facesMessage.getDetail());
+ }
+
+ /**
+ * Verify that a message can be added to a control based on either it's absolute client id
+ * or it's local id. Verify that if the component cannot be found, a global message is created.
+ */
+ @Test
+ public void testStatusMessagesForControlGetTransferedToFacesMessages()
+ {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
+ UIViewRoot viewRoot = new UIViewRoot();
+ UIComponent form = new UINamingContainer();
+ form.setId("form");
+ UIComponent input = new UIInput();
+ input.setId("input");
+ form.getChildren().add(input);
+ viewRoot.getChildren().add(form);
+ facesContext.setViewRoot(viewRoot);
+
+ facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
+ StatusMessages statusMessages = getStatusMessagesInstance();
+ statusMessages.addToControl("input", StatusMessage.Severity.WARN, "First validation message for input");
+ statusMessages.addToControl("form:input", StatusMessage.Severity.WARN, "Second validation message for input");
+ statusMessages.addToControl("NO_SUCH_ID", StatusMessage.Severity.WARN, "Validation message that becomes global");
+
+ assertEquals(statusMessages.getKeyedMessages().size(), 3);
+ assertEquals(facesContext.getMessageList().size(), 0);
+
+ facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
+ statusMessages.onBeforeRender();
+
+ assertEquals(statusMessages.getGlobalMessages().size(), 0);
+ assertEquals(facesContext.getMessageList().size(), 3);
+ assertEquals(facesContext.getMessageList(null).size(), 1);
+ FacesMessage globalMessage = facesContext.getMessageList(null).get(0);
+ assertSame(globalMessage.getSeverity(), FacesMessage.SEVERITY_WARN);
+ assertEquals(globalMessage.getSummary(), "Validation message that becomes global");
+ List<FacesMessage> messagesForInput = facesContext.getMessageList("form:input");
+ assertEquals(messagesForInput.size(), 2);
+ assertEquals(messagesForInput.get(0).getSummary(), "First validation message for input");
+ assertEquals(messagesForInput.get(1).getSummary(), "Second validation message for input");
+ }
+
+ // TODO either test TransferStatusMessagesListener here or create a dedicated test for it; to test lookup of StatusMessages from listener
+
+ private void installMockFacesContext()
+ {
+ new MockFacesContext(new MockApplication(), true).setCurrent();
+ }
+
+ private void activateConversationContext()
+ {
+ ConversationContext.instance().setBeanStore(new ConcurrentHashMapBeanStore());
+ ConversationContext.instance().setActive(true);
+ }
+
+ /**
+ * Retrieve the StatusMessage instance, which is expected to be the type FacesMessages.
+ */
+ private StatusMessages getStatusMessagesInstance()
+ {
+ StatusMessages statusMessages = getCurrentManager().getInstanceByType(StatusMessages.class, new AnnotationLiteral<Faces>() {});
+ assert statusMessages instanceof FacesMessages;
+ return statusMessages;
+ }
+}
Deleted: modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesStatusMessagesTest.java
===================================================================
--- modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesStatusMessagesTest.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/faces/src/test/java/org/jboss/seam/faces/FacesStatusMessagesTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,149 +0,0 @@
-package org.jboss.seam.faces;
-
-import java.util.List;
-import javax.faces.application.FacesMessage;
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIInput;
-import javax.faces.component.UINamingContainer;
-import javax.faces.component.UIViewRoot;
-import static org.testng.Assert.*;
-
-import javax.faces.context.FacesContext;
-import javax.faces.event.PhaseId;
-import org.jboss.seam.el.Expressions;
-import org.jboss.seam.international.Interpolator;
-import org.jboss.seam.international.LocaleProducer;
-import org.jboss.seam.international.StatusMessage;
-import org.jboss.seam.international.StatusMessages;
-import org.jboss.seam.mock.faces.MockApplication;
-import org.jboss.seam.mock.faces.MockFacesContext;
-import org.jboss.testharness.impl.packaging.Artifact;
-import org.jboss.testharness.impl.packaging.Classes;
-import org.jboss.testharness.impl.packaging.jsr299.BeansXml;
-import org.jboss.webbeans.context.ConversationContext;
-import org.jboss.webbeans.context.api.helpers.ConcurrentHashMapBeanStore;
-import org.jboss.webbeans.test.AbstractWebBeansTest;
-import org.testng.annotations.Test;
-
-/**
- * First and foremost, ensure that FacesStatusMessage is configured properly
- * to specialize StatusMessage and will thus load successfully. Once loaded,
- * verify that FacesStatusMessage adds the appropriate JSF-specific functionality
- * to the status message repository.
- *
- * @author Dan Allen
- *
- * @see FacesStatusMessages
- * @see StatusMessages
- */
- at Artifact(addCurrentPackage = false)
- at BeansXml("beans.xml")
- at Classes(
-{
- FacesStatusMessages.class, StatusMessages.class, Interpolator.class, Expressions.class, LocaleProducer.class
-})
-public class FacesStatusMessagesTest extends AbstractWebBeansTest
-{
- @Override
- public void beforeMethod()
- {
- super.beforeMethod();
- activateConversationContext();
- installMockFacesContext();
- }
-
- /**
- * Test that the StatusMessage objects properly tranfer to FacesMessage objects
- * upon the call to onBeforeRender().
- */
- @Test
- public void testGlobalStatusMessagesGetTransferedToFacesMessages()
- {
- FacesContext facesContext = FacesContext.getCurrentInstance();
- facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
- StatusMessages statusMessages = getStatusMessagesInstance();
-
- statusMessages.add("You've booked a night at {0}. Bon chance!", "Mandalay Bay");
-
- assertEquals(statusMessages.getGlobalMessages().size(), 1);
- assertEquals(facesContext.getMessageList().size(), 0);
-
- facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
- statusMessages.onBeforeRender();
-
- assertEquals(statusMessages.getGlobalMessages().size(), 0);
- assertEquals(facesContext.getMessageList().size(), 1);
- assertEquals(facesContext.getMessageList(null).size(), 1);
- FacesMessage facesMessage = facesContext.getMessageList().get(0);
- assertEquals(facesMessage.getSeverity(), FacesMessage.SEVERITY_INFO);
- assertEquals(facesMessage.getSummary(), "You've booked a night at Mandalay Bay. Bon chance!");
- // NOTE this assignment happens inside the FacesMessage implementation
- assertEquals(facesMessage.getSummary(), facesMessage.getDetail());
- }
-
- /**
- * Verify that a message can be added to a control based on either it's absolute client id
- * or it's local id. Verify that if the component cannot be found, a global message is created.
- */
- @Test
- public void testStatusMessagesForControlGetTransferedToFacesMessages()
- {
- FacesContext facesContext = FacesContext.getCurrentInstance();
-
- facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
- UIViewRoot viewRoot = new UIViewRoot();
- UIComponent form = new UINamingContainer();
- form.setId("form");
- UIComponent input = new UIInput();
- input.setId("input");
- form.getChildren().add(input);
- viewRoot.getChildren().add(form);
- facesContext.setViewRoot(viewRoot);
-
- facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
- StatusMessages statusMessages = getStatusMessagesInstance();
- statusMessages.addToControl("input", StatusMessage.Severity.WARN, "First validation message for input");
- statusMessages.addToControl("form:input", StatusMessage.Severity.WARN, "Second validation message for input");
- statusMessages.addToControl("NO_SUCH_ID", StatusMessage.Severity.WARN, "Validation message that becomes global");
-
- assertEquals(statusMessages.getKeyedMessages().size(), 3);
- assertEquals(facesContext.getMessageList().size(), 0);
-
- facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
- statusMessages.onBeforeRender();
-
- assertEquals(statusMessages.getGlobalMessages().size(), 0);
- assertEquals(facesContext.getMessageList().size(), 3);
- assertEquals(facesContext.getMessageList(null).size(), 1);
- FacesMessage globalMessage = facesContext.getMessageList(null).get(0);
- assertSame(globalMessage.getSeverity(), FacesMessage.SEVERITY_WARN);
- assertEquals(globalMessage.getSummary(), "Validation message that becomes global");
- List<FacesMessage> messagesForInput = facesContext.getMessageList("form:input");
- assertEquals(messagesForInput.size(), 2);
- assertEquals(messagesForInput.get(0).getSummary(), "First validation message for input");
- assertEquals(messagesForInput.get(1).getSummary(), "Second validation message for input");
- }
-
- // TODO either test TransferStatusMessagesListener here or create a dedicated test for it; to test lookup of StatusMessages from listener
-
- private void installMockFacesContext()
- {
- new MockFacesContext(new MockApplication(), true).setCurrent();
- }
-
- private void activateConversationContext()
- {
- ConversationContext.instance().setBeanStore(new ConcurrentHashMapBeanStore());
- ConversationContext.instance().setActive(true);
- }
-
- /**
- * Retrieve the StatusMessage instance, which is expected to be the type FacesMessages.
- */
- private StatusMessages getStatusMessagesInstance()
- {
- StatusMessages statusMessages = getCurrentManager().getInstanceByType(StatusMessages.class);
- assert statusMessages instanceof FacesStatusMessages;
- return statusMessages;
- }
-}
Modified: modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessages.java
===================================================================
--- modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessages.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessages.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -376,9 +376,9 @@
* Add an array of {@link ConstraintViolation} objects from Bean Validation. Each message will
* be added with a severity of WARN.
*/
- public void add(ConstraintViolation[] cvs)
+ public void add(ConstraintViolation<?>[] cvs)
{
- for (ConstraintViolation cv : cvs)
+ for (ConstraintViolation<?> cv : cvs)
{
add(cv);
}
@@ -390,9 +390,9 @@
*
* The name of the property that was validated will be used as the widget ID
*/
- public void addToControls(ConstraintViolation[] cvs)
+ public void addToControls(ConstraintViolation<?>[] cvs)
{
- for (ConstraintViolation cv : cvs)
+ for (ConstraintViolation<?> cv : cvs)
{
addToControl(cv);
}
@@ -402,7 +402,7 @@
* Add a {@link ConstraintViolation} from Bean Validation. The message will
* be added with a severity of WARN.
*/
- public void add(ConstraintViolation cv)
+ public void add(ConstraintViolation<?> cv)
{
add(WARN, cv.getMessage());
}
@@ -413,7 +413,7 @@
*
* The name of the property that was validated will be used as the widget ID
*/
- public void addToControl(ConstraintViolation cv)
+ public void addToControl(ConstraintViolation<?> cv)
{
String propertyName = cv.getPropertyPath().substring(cv.getPropertyPath().lastIndexOf(".") + 1);
addToControl(propertyName, cv);
@@ -425,7 +425,7 @@
*
* You can also specify the id of the widget to add the message to
*/
- public void addToControl(String id, ConstraintViolation cv)
+ public void addToControl(String id, ConstraintViolation<?> cv)
{
addToControl(id, WARN, cv.getMessage());
}
Added: modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessagesWrapper.java
===================================================================
--- modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessagesWrapper.java (rev 0)
+++ modules/trunk/international/src/main/java/org/jboss/seam/international/StatusMessagesWrapper.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -0,0 +1,181 @@
+package org.jboss.seam.international;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.ConstraintViolation;
+
+import org.jboss.seam.international.StatusMessage.Severity;
+
+/**
+ * A abstract wrapper class that delegates all operations to the StatusMessages
+ * instance. It's up to the implementation to provide access to the
+ * StatusMessages instance, preferably obtained through constructor injection.
+ * The intent is for this class to be extended to wrap view layer specific
+ * functionality around the StatusMessages component.
+ *
+ * @author Dan Allen
+ */
+public abstract class StatusMessagesWrapper extends StatusMessages
+{
+ public abstract StatusMessages getStatusMessages();
+
+ @Override
+ public abstract void onBeforeRender();
+
+ @Override
+ public void add(ConstraintViolation<?> cv)
+ {
+ getStatusMessages().add(cv);
+ }
+
+ @Override
+ public void add(ConstraintViolation<?>[] cvs)
+ {
+ getStatusMessages().add(cvs);
+ }
+
+ @Override
+ public void add(Severity severity, String messageTemplate, Object... params)
+ {
+ getStatusMessages().add(severity, messageTemplate, params);
+ }
+
+ @Override
+ public void add(Severity severity, String key, String detailKey, String messageTemplate, String messageDetailTemplate, Object... params)
+ {
+ getStatusMessages().add(severity, key, detailKey, messageTemplate, messageDetailTemplate, params);
+ }
+
+ @Override
+ public void add(String messageTemplate, Object... params)
+ {
+ getStatusMessages().add(messageTemplate, params);
+ }
+
+ @Override
+ public void addFromResourceBundle(Severity severity, String key, Object... params)
+ {
+ getStatusMessages().addFromResourceBundle(severity, key, params);
+ }
+
+ @Override
+ public void addFromResourceBundle(String key, Object... params)
+ {
+ getStatusMessages().addFromResourceBundle(key, params);
+ }
+
+ @Override
+ public void addFromResourceBundleOrDefault(Severity severity, String key, String defaultMessageTemplate, Object... params)
+ {
+ getStatusMessages().addFromResourceBundleOrDefault(severity, key, defaultMessageTemplate, params);
+ }
+
+ @Override
+ public void addFromResourceBundleOrDefault(String key, String defaultMessageTemplate, Object... params)
+ {
+ getStatusMessages().addFromResourceBundleOrDefault(key, defaultMessageTemplate, params);
+ }
+
+ @Override
+ public void addToControl(ConstraintViolation<?> cv)
+ {
+ getStatusMessages().addToControl(cv);
+ }
+
+ @Override
+ public void addToControl(String id, ConstraintViolation<?> cv)
+ {
+ getStatusMessages().addToControl(id, cv);
+ }
+
+ @Override
+ public void addToControl(String id, Severity severity, String messageTemplate, Object... params)
+ {
+ getStatusMessages().addToControl(id, severity, messageTemplate, params);
+ }
+
+ @Override
+ public void addToControl(String id, Severity severity, String key, String messageTemplate, Object... params)
+ {
+ getStatusMessages().addToControl(id, severity, key, messageTemplate, params);
+ }
+
+ @Override
+ public void addToControl(String id, String messageTemplate, Object... params)
+ {
+ getStatusMessages().addToControl(id, messageTemplate, params);
+ }
+
+ @Override
+ public void addToControlFromResourceBundle(String id, Severity severity, String key, Object... params)
+ {
+ getStatusMessages().addToControlFromResourceBundle(id, severity, key, params);
+ }
+
+ @Override
+ public void addToControlFromResourceBundle(String id, String key, Object... params)
+ {
+ getStatusMessages().addToControlFromResourceBundle(id, key, params);
+ }
+
+ @Override
+ public void addToControlFromResourceBundleOrDefault(String id, Severity severity, String key, String defaultMessageTemplate, Object... params)
+ {
+ getStatusMessages().addToControlFromResourceBundleOrDefault(id, severity, key, defaultMessageTemplate, params);
+ }
+
+ @Override
+ public void addToControlFromResourceBundleOrDefault(String id, String key, String defaultMessageTemplate, Object... params)
+ {
+ getStatusMessages().addToControlFromResourceBundleOrDefault(id, key, defaultMessageTemplate, params);
+ }
+
+ @Override
+ public void addToControls(ConstraintViolation<?>[] cvs)
+ {
+ getStatusMessages().addToControls(cvs);
+ }
+
+ @Override
+ public void clear()
+ {
+ getStatusMessages().clear();
+ }
+
+ @Override
+ public void clearGlobalMessages()
+ {
+ getStatusMessages().clearGlobalMessages();
+ }
+
+ @Override
+ public void clearKeyedMessages()
+ {
+ getStatusMessages().clearKeyedMessages();
+ }
+
+ @Override
+ public void clearKeyedMessages(String id)
+ {
+ getStatusMessages().clearKeyedMessages(id);
+ }
+
+ @Override
+ public List<StatusMessage> getGlobalMessages()
+ {
+ return getStatusMessages().getGlobalMessages();
+ }
+
+ @Override
+ public Map<String, List<StatusMessage>> getKeyedMessages()
+ {
+ return getStatusMessages().getKeyedMessages();
+ }
+
+ @Override
+ public List<StatusMessage> getKeyedMessages(String id)
+ {
+ return getStatusMessages().getKeyedMessages(id);
+ }
+}
Modified: modules/trunk/international/src/test/java/org/jboss/seam/international/InterpolatorTest.java
===================================================================
--- modules/trunk/international/src/test/java/org/jboss/seam/international/InterpolatorTest.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/international/src/test/java/org/jboss/seam/international/InterpolatorTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,15 +1,18 @@
package org.jboss.seam.international;
+import static org.testng.Assert.assertEquals;
+
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+
import javax.el.CompositeELResolver;
import javax.el.ELContext;
+
import org.jboss.seam.el.AbstractELResolver;
-import static org.testng.Assert.*;
-
import org.jboss.seam.el.Expressions;
+import org.jboss.seam.el.ExpressionsProducer;
import org.jboss.testharness.impl.packaging.Artifact;
import org.jboss.testharness.impl.packaging.Classes;
import org.jboss.webbeans.test.AbstractWebBeansTest;
@@ -26,7 +29,7 @@
* @see LocaleProducer
*/
@Artifact(addCurrentPackage = false)
- at Classes({Interpolator.class, Expressions.class, LocaleProducer.class})
+ at Classes({Interpolator.class, Expressions.class, ExpressionsProducer.class, LocaleProducer.class})
public class InterpolatorTest extends AbstractWebBeansTest
{
@Override
Modified: modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesTest.java
===================================================================
--- modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesTest.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,12 +1,14 @@
package org.jboss.seam.international;
+import static org.testng.Assert.assertEquals;
+
import org.jboss.seam.el.Expressions;
+import org.jboss.seam.el.ExpressionsProducer;
import org.jboss.testharness.impl.packaging.Artifact;
import org.jboss.testharness.impl.packaging.Classes;
import org.jboss.webbeans.context.ConversationContext;
import org.jboss.webbeans.context.api.helpers.ConcurrentHashMapBeanStore;
import org.jboss.webbeans.test.AbstractWebBeansTest;
-import static org.testng.Assert.*;
import org.testng.annotations.Test;
/**
@@ -18,7 +20,7 @@
@Artifact(addCurrentPackage = false)
@Classes(
{
- StatusMessages.class, Interpolator.class, Expressions.class, LocaleProducer.class
+ StatusMessages.class, Interpolator.class, Expressions.class, ExpressionsProducer.class, LocaleProducer.class
})
public class StatusMessagesTest extends AbstractWebBeansTest
{
Modified: modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesUnitTest.java
===================================================================
--- modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesUnitTest.java 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/international/src/test/java/org/jboss/seam/international/StatusMessagesUnitTest.java 2009-05-27 04:22:02 UTC (rev 11012)
@@ -1,9 +1,16 @@
package org.jboss.seam.international;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+
import java.util.List;
+
import javax.validation.ConstraintDescriptor;
import javax.validation.ConstraintViolation;
-import static org.testng.Assert.*;
+
import org.testng.annotations.Test;
/**
@@ -93,7 +100,7 @@
public void testAddGlobalMessageFromConstraintViolation()
{
StatusMessages statusMessages = getStatusMessagesInstance();
- ConstraintViolation violation = new ConstraintViolationStub("Invalid number", "creditCardNumber");
+ ConstraintViolation<Object> violation = new ConstraintViolationStub("Invalid number", "creditCardNumber");
statusMessages.add(violation);
assertEquals(statusMessages.getGlobalMessages().size(), 1);
assertEquals(statusMessages.getKeyedMessages().size(), 0);
@@ -111,9 +118,9 @@
public void testAddMessageToControlsDynamicallyFromConstraintViolation()
{
StatusMessages statusMessages = getStatusMessagesInstance();
- ConstraintViolation firstNameViolation = new ConstraintViolationStub("Too short", "firstName");
- ConstraintViolation lastNameViolation = new ConstraintViolationStub("Too long", "lastName");
- ConstraintViolation usernameViolation = new ConstraintViolationStub("Already taken", "account.username");
+ ConstraintViolation<Object> firstNameViolation = new ConstraintViolationStub("Too short", "firstName");
+ ConstraintViolation<Object> lastNameViolation = new ConstraintViolationStub("Too long", "lastName");
+ ConstraintViolation<Object> usernameViolation = new ConstraintViolationStub("Already taken", "account.username");
statusMessages.addToControl(firstNameViolation);
statusMessages.addToControls(new ConstraintViolation[] { lastNameViolation, usernameViolation });
assertEquals(statusMessages.getGlobalMessages().size(), 0);
@@ -198,7 +205,7 @@
}
}
- private class ConstraintViolationStub implements ConstraintViolation
+ private class ConstraintViolationStub implements ConstraintViolation<Object>
{
private String message;
private String propertyPath;
@@ -239,12 +246,12 @@
throw new UnsupportedOperationException("Not supported by stub.");
}
- public ConstraintDescriptor getConstraintDescriptor()
+ public ConstraintDescriptor<?> getConstraintDescriptor()
{
throw new UnsupportedOperationException("Not supported by stub.");
}
- public Class getRootBeanClass()
+ public Class<Object> getRootBeanClass()
{
throw new UnsupportedOperationException("Not supported by stub.");
}
Modified: modules/trunk/parent/pom.xml
===================================================================
--- modules/trunk/parent/pom.xml 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/parent/pom.xml 2009-05-27 04:22:02 UTC (rev 11012)
@@ -93,6 +93,7 @@
<module>../version-matrix</module>
<module>../mock</module>
<module>../bridge-api</module>
+ <module>../beans</module>
<module>../el</module>
<module>../international</module>
<module>../web</module>
Modified: modules/trunk/version-matrix/pom.xml
===================================================================
--- modules/trunk/version-matrix/pom.xml 2009-05-27 04:21:11 UTC (rev 11011)
+++ modules/trunk/version-matrix/pom.xml 2009-05-27 04:22:02 UTC (rev 11012)
@@ -246,6 +246,12 @@
<artifactId>jbpm-jpdl</artifactId>
<version>3.2.2</version>
</dependency>
+
+ <dependency>
+ <groupId>${seam.groupId}</groupId>
+ <artifactId>seam-beans</artifactId>
+ <version>${seam.version}</version>
+ </dependency>
<dependency>
<groupId>${seam.groupId}</groupId>
More information about the seam-commits
mailing list