Author: shane.bryzak(a)jboss.com
Date: 2009-12-07 20:45:36 -0500 (Mon, 07 Dec 2009)
New Revision: 11791
Modified:
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/ExecutionHandler.java
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/MarshalUtils.java
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/Model.java
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/ModelHandler.java
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/wrapper/BeanWrapper.java
Log:
model response marshalling, cleaned up some code
Modified:
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/ExecutionHandler.java
===================================================================
---
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/ExecutionHandler.java 2009-12-08
01:44:54 UTC (rev 11790)
+++
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/ExecutionHandler.java 2009-12-08
01:45:36 UTC (rev 11791)
@@ -187,7 +187,7 @@
for (Call call : calls)
{
- MarshalUtils.marshalResult(call, out);
+ MarshalUtils.marshalCallResult(call, out);
}
out.write(BODY_TAG_CLOSE);
Modified: modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/MarshalUtils.java
===================================================================
---
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/MarshalUtils.java 2009-12-08
01:44:54 UTC (rev 11790)
+++
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/MarshalUtils.java 2009-12-08
01:45:36 UTC (rev 11791)
@@ -2,81 +2,126 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.util.List;
+import org.jboss.seam.remoting.model.Model;
import org.jboss.seam.remoting.wrapper.BeanWrapper;
import org.jboss.seam.remoting.wrapper.Wrapper;
/**
- *
- *
+ *
+ *
* @author Shane Bryzak
*/
public class MarshalUtils
{
- private static final byte[] RESULT_TAG_OPEN_START = "<result
id=\"".getBytes();
- private static final byte[] RESULT_TAG_OPEN_END = "\">".getBytes();
- private static final byte[] RESULT_TAG_OPEN = "<result>".getBytes();
- private static final byte[] RESULT_TAG_CLOSE = "</result>".getBytes();
+ private static final byte[] RESULT_TAG_OPEN_START = "<result
id=\"".getBytes();
+ private static final byte[] RESULT_TAG_OPEN_END = "\">".getBytes();
+ private static final byte[] RESULT_TAG_OPEN = "<result>".getBytes();
+ private static final byte[] RESULT_TAG_CLOSE =
"</result>".getBytes();
+
+ private static final byte[] MODEL_TAG_OPEN_START = "<model
uid=\"".getBytes();
+ private static final byte[] MODEL_TAG_OPEN_END = "\">".getBytes();
+ private static final byte[] MODEL_TAG_CLOSE = "</model>".getBytes();
- private static final byte[] VALUE_TAG_OPEN = "<value>".getBytes();
- private static final byte[] VALUE_TAG_CLOSE = "</value>".getBytes();
-
- private static final byte[] EXCEPTION_TAG_OPEN =
"<exception>".getBytes();
- private static final byte[] EXCEPTION_TAG_CLOSE =
"</exception>".getBytes();
-
- private static final byte[] MESSAGE_TAG_OPEN = "<message>".getBytes();
- private static final byte[] MESSAGE_TAG_CLOSE =
"</message>".getBytes();
+ private static final byte[] VALUE_TAG_OPEN = "<value>".getBytes();
+ private static final byte[] VALUE_TAG_CLOSE = "</value>".getBytes();
- public static void marshalResult(Call call, OutputStream out)
- throws IOException
- {
- if (call.getId() != null)
- {
- out.write(RESULT_TAG_OPEN_START);
- out.write(call.getId().getBytes());
- out.write(RESULT_TAG_OPEN_END);
- }
- else
- out.write(RESULT_TAG_OPEN);
+ private static final byte[] EXCEPTION_TAG_OPEN =
"<exception>".getBytes();
+ private static final byte[] EXCEPTION_TAG_CLOSE =
"</exception>".getBytes();
- if (call.getException() != null)
- {
- out.write(EXCEPTION_TAG_OPEN);
- out.write(MESSAGE_TAG_OPEN);
- call.getContext().createWrapperFromObject(call.getException().getMessage(),
"").marshal(out);
- out.write(MESSAGE_TAG_CLOSE);
- out.write(EXCEPTION_TAG_CLOSE);
- }
- else
- {
- out.write(VALUE_TAG_OPEN);
+ private static final byte[] MESSAGE_TAG_OPEN =
"<message>".getBytes();
+ private static final byte[] MESSAGE_TAG_CLOSE =
"</message>".getBytes();
+
+ public static void marshalCallResult(Call call, OutputStream out)
+ throws IOException
+ {
+ if (call.getId() != null)
+ {
+ out.write(RESULT_TAG_OPEN_START);
+ out.write(call.getId().getBytes());
+ out.write(RESULT_TAG_OPEN_END);
+ }
+ else
+ {
+ out.write(RESULT_TAG_OPEN);
+ }
+
+ if (call.getException() != null)
+ {
+ marshalException(call.getException(), call.getContext(), out);
+ }
+ else
+ {
+ out.write(VALUE_TAG_OPEN);
+ call.getContext().createWrapperFromObject(call.getResult(), "")
+ .marshal(out);
+ out.write(VALUE_TAG_CLOSE);
+
+ out.write(RequestHandler.REFS_TAG_OPEN);
+ marshalRefs(call.getContext().getOutRefs(), call.getConstraints(), out);
+ out.write(RequestHandler.REFS_TAG_CLOSE);
+ }
+
+ out.write(RESULT_TAG_CLOSE);
+ }
- call.getContext().createWrapperFromObject(call.getResult(),
"").marshal(out);
+ public static void marshalException(Throwable exception, CallContext ctx, OutputStream
out)
+ throws IOException
+ {
+ out.write(EXCEPTION_TAG_OPEN);
+ out.write(MESSAGE_TAG_OPEN);
+ ctx.createWrapperFromObject(exception.getMessage(), "").marshal(out);
+ out.write(MESSAGE_TAG_CLOSE);
+ out.write(EXCEPTION_TAG_CLOSE);
+ }
- out.write(VALUE_TAG_CLOSE);
+ public static void marshalModel(Model model, OutputStream out)
+ throws IOException
+ {
+ out.write(MODEL_TAG_OPEN_START);
+ out.write(model.getId().getBytes());
+ out.write(MODEL_TAG_OPEN_END);
+
+ for (String alias : model.getBeanProperties().keySet())
+ {
+ Model.BeanProperty property = model.getBeanProperties().get(alias);
+
+ out.write(VALUE_TAG_OPEN);
+ model.getCallContext().createWrapperFromObject(property.getValue(),
"")
+ .marshal(out);
+ out.write(VALUE_TAG_CLOSE);
+ }
+
+ out.write(RequestHandler.REFS_TAG_OPEN);
+ marshalRefs(model.getCallContext().getOutRefs(), null, out);
+ out.write(RequestHandler.REFS_TAG_CLOSE);
+
+ out.write(MODEL_TAG_CLOSE);
+ }
- out.write(RequestHandler.REFS_TAG_OPEN);
-
- // Using a for-loop, because stuff can get added to outRefs as we recurse the
object graph
- for (int i = 0; i < call.getContext().getOutRefs().size(); i++)
- {
- Wrapper wrapper = call.getContext().getOutRefs().get(i);
-
+ public static void marshalRefs(List<Wrapper> refs, List<String>
constraints,
+ OutputStream out)
+ throws IOException
+ {
+ for (int i = 0; i < refs.size(); i++)
+ {
+ Wrapper wrapper = refs.get(i);
+
out.write(RequestHandler.REF_TAG_OPEN_START);
out.write(Integer.toString(i).getBytes());
out.write(RequestHandler.REF_TAG_OPEN_END);
-
- if (wrapper instanceof BeanWrapper && call.getConstraints() != null)
- ((BeanWrapper) wrapper).serialize(out, call.getConstraints());
+
+ if (wrapper instanceof BeanWrapper && constraints != null)
+ {
+ ((BeanWrapper) wrapper).serialize(out, constraints);
+ }
else
- wrapper.serialize(out);
-
+ {
+ wrapper.serialize(out);
+ }
+
out.write(RequestHandler.REF_TAG_CLOSE);
- }
-
- out.write(RequestHandler.REFS_TAG_CLOSE);
- }
-
- out.write(RESULT_TAG_CLOSE);
- }
+ }
+ }
}
Modified: modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/Model.java
===================================================================
---
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/Model.java 2009-12-08
01:44:54 UTC (rev 11790)
+++
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/Model.java 2009-12-08
01:45:36 UTC (rev 11791)
@@ -2,11 +2,14 @@
import java.io.Serializable;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
@@ -14,6 +17,11 @@
import org.jboss.seam.remoting.Call;
import org.jboss.seam.remoting.CallContext;
+/**
+ * Manages a model request
+ *
+ * @author Shane Bryzak
+ */
public class Model implements Serializable
{
private static final long serialVersionUID = 8318288750036758325L;
@@ -22,16 +30,79 @@
private String id;
private CallContext callContext;
- private class BeanProperty
+ public class BeanProperty
{
- public Bean<?> bean;
- public String propertyName;
+ private Bean<?> bean;
+ private String propertyName;
+ private Object value;
public BeanProperty(Bean<?> bean, String propertyName)
{
this.bean = bean;
this.propertyName = propertyName;
}
+
+ public Bean<?> getBean()
+ {
+ return bean;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void evaluate(CreationalContext ctx)
+ {
+ Object instance = bean.create(ctx);
+
+ if (propertyName != null)
+ {
+ try
+ {
+ Field f = bean.getBeanClass().getField(propertyName);
+ boolean accessible = f.isAccessible();
+ try
+ {
+ f.setAccessible(true);
+ value = f.get(instance);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(
+ "Exception reading model property " + propertyName +
+ " from bean [" + bean + "]");
+ }
+ finally
+ {
+ f.setAccessible(accessible);
+ }
+ }
+ catch (NoSuchFieldException ex)
+ {
+ // Try the getter method
+ String methodName = "get" + propertyName.substring(0,
1).toUpperCase() +
+ propertyName.substring(1);
+
+ try
+ {
+ Method m = bean.getBeanClass().getMethod(methodName);
+ value = m.invoke(instance);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(
+ "Exception reading model property " + propertyName +
+ " from bean [" + bean + "]");
+ }
+ }
+ }
+ else
+ {
+ this.value = instance;
+ }
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
}
private Map<String, BeanProperty> beanProperties;
@@ -44,6 +115,25 @@
beanProperties = new HashMap<String, BeanProperty>();
}
+ /**
+ * Evaluate each of the model's bean properties, expressions, etc and
+ * store the values in the BeanProperty map.
+ */
+ public void evaluate()
+ {
+
+ for (String alias : beanProperties.keySet())
+ {
+ BeanProperty property = beanProperties.get(alias);
+ property.evaluate(beanManager.createCreationalContext(property.getBean()));
+ }
+ }
+
+ public Map<String,BeanProperty> getBeanProperties()
+ {
+ return beanProperties;
+ }
+
public String getId()
{
return id;
Modified:
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/ModelHandler.java
===================================================================
---
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/ModelHandler.java 2009-12-08
01:44:54 UTC (rev 11790)
+++
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/model/ModelHandler.java 2009-12-08
01:45:36 UTC (rev 11791)
@@ -18,6 +18,7 @@
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jboss.seam.remoting.Call;
+import org.jboss.seam.remoting.MarshalUtils;
import org.jboss.seam.remoting.RequestContext;
import org.jboss.seam.remoting.RequestHandler;
import org.jboss.seam.remoting.wrapper.Wrapper;
@@ -69,6 +70,7 @@
}
Set<Model> models = new HashSet<Model>();
+ Call action = null;
for (Element modelElement : (List<Element>)
env.element("body").elements("model"))
{
@@ -78,8 +80,8 @@
if ("fetch".equals(operation))
{
Model model = registry.createModel();
+ models.add(model);
- Call action = null;
if (modelElement.elements("action").size() > 0)
{
Element actionElement = modelElement.element("action");
@@ -136,13 +138,25 @@
if (action != null)
{
- action.execute();
+ action.execute();
}
}
}
- ctx.setConversationId(conversation.getId());
- marshalResponse(models, ctx, response.getOutputStream());
+ if (action != null && action.getException() != null)
+ {
+ out.write(ENVELOPE_TAG_OPEN);
+ out.write(BODY_TAG_OPEN);
+ MarshalUtils.marshalException(action.getException(), action.getContext(), out);
+ out.write(BODY_TAG_CLOSE);
+ out.write(ENVELOPE_TAG_CLOSE);
+ out.flush();
+ }
+ else
+ {
+ ctx.setConversationId(conversation.getId());
+ marshalResponse(models, ctx, response.getOutputStream());
+ }
}
private void marshalResponse(Set<Model> models, RequestContext ctx,
@@ -165,7 +179,7 @@
for (Model model : models)
{
- //MarshalUtils.marshalResult(call, out);
+ MarshalUtils.marshalModel(model, out);
}
out.write(BODY_TAG_CLOSE);
Modified:
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/wrapper/BeanWrapper.java
===================================================================
---
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/wrapper/BeanWrapper.java 2009-12-08
01:44:54 UTC (rev 11790)
+++
modules/remoting/trunk/src/main/java/org/jboss/seam/remoting/wrapper/BeanWrapper.java 2009-12-08
01:45:36 UTC (rev 11791)
@@ -49,12 +49,14 @@
if (bean != null)
{
value = bean.create(beanManager.createCreationalContext(bean));
- } else
+ }
+ else
{
try
{
value = Class.forName(beanType).newInstance();
- } catch (Exception ex)
+ }
+ catch (Exception ex)
{
throw new RuntimeException("Could not unmarshal bean element: "
+ element.getText(), ex);
@@ -62,12 +64,13 @@
}
}
+ @SuppressWarnings("unchecked")
@Override
public void unmarshal()
{
- List members = element.elements("member");
+ List<Element> members = element.elements("member");
- for (Element member : (List<Element>) members)
+ for (Element member : members)
{
String name = member.attributeValue("name");
@@ -108,7 +111,8 @@
{
// First check the declared fields
field = cls.getDeclaredField(name);
- } catch (NoSuchFieldException ex)
+ }
+ catch (NoSuchFieldException ex)
{
// Couldn't find the field.. try the superclass
cls = cls.getSuperclass();
@@ -131,7 +135,8 @@
{
fieldValue = w.convert(method != null ? method
.getGenericParameterTypes()[0] : field.getGenericType());
- } catch (ConversionException ex)
+ }
+ catch (ConversionException ex)
{
throw new RuntimeException(
"Could not convert value while unmarshaling", ex);
@@ -143,12 +148,14 @@
try
{
method.invoke(value, fieldValue);
- } catch (Exception e)
+ }
+ catch (Exception e)
{
throw new RuntimeException(String.format(
"Could not invoke setter method [%s]",
method.getName()));
}
- } else
+ }
+ else
{
// Otherwise try to set the field value directly
boolean accessible = field.isAccessible();
@@ -157,10 +164,12 @@
if (!accessible)
field.setAccessible(true);
field.set(value, fieldValue);
- } catch (Exception ex)
+ }
+ catch (Exception ex)
{
throw new RuntimeException("Could not set field value.", ex);
- } finally
+ }
+ finally
{
field.setAccessible(accessible);
}
@@ -170,12 +179,16 @@
public Object convert(Type type) throws ConversionException
{
- if (type instanceof Class
- && ((Class) type).isAssignableFrom(value.getClass()))
+ if (type instanceof Class<?>
+ && ((Class<?>) type).isAssignableFrom(value.getClass()))
+ {
return value;
+ }
else
+ {
throw new ConversionException(String.format(
"Value [%s] cannot be converted to type [%s].", value, type));
+ }
}
public void marshal(OutputStream out) throws IOException
@@ -200,7 +213,7 @@
{
out.write(BEAN_START_TAG_OPEN);
- Class cls = value.getClass();
+ Class<?> cls = value.getClass();
/**
* @todo This is a hack to get the "real" class - find out if there is
an
@@ -217,13 +230,17 @@
}
// TODO fix this, bean might not have a name
- Bean bean = beanManager.getBeans(cls).iterator().next();
+ Bean<?> bean = beanManager.getBeans(cls).iterator().next();
String componentName = bean.getName();
if (componentName != null)
+ {
out.write(componentName.getBytes());
+ }
else
+ {
out.write(cls.getName().getBytes());
+ }
out.write(BEAN_START_TAG_CLOSE);
@@ -251,7 +268,8 @@
try
{
f = cls.getField(propertyName);
- } catch (NoSuchFieldException ex)
+ }
+ catch (NoSuchFieldException ex)
{
}
@@ -265,7 +283,8 @@
f.setAccessible(true);
context.createWrapperFromObject(f.get(value), fieldPath)
.marshal(out);
- } else
+ }
+ else
{
Method accessor = null;
try
@@ -273,14 +292,16 @@
accessor = cls.getMethod(String.format("get%s%s",
Character.toUpperCase(propertyName.charAt(0)),
propertyName.substring(1)));
- } catch (NoSuchMethodException ex)
+ }
+ catch (NoSuchMethodException ex)
{
try
{
accessor = cls.getMethod(String.format("is%s%s",
Character.toUpperCase(propertyName.charAt(0)),
propertyName.substring(1)));
- } catch (NoSuchMethodException ex2)
+ }
+ catch (NoSuchMethodException ex2)
{
// uh oh... continue with the next one
continue;
@@ -291,17 +312,20 @@
{
context.createWrapperFromObject(accessor.invoke(value),
fieldPath).marshal(out);
- } catch (InvocationTargetException ex)
+ }
+ catch (InvocationTargetException ex)
{
throw new RuntimeException(String.format(
"Failed to read property [%s] for object [%s]",
propertyName, value));
}
}
- } catch (IllegalAccessException ex)
+ }
+ catch (IllegalAccessException ex)
{
throw new RuntimeException("Error reading value from field.");
- } finally
+ }
+ finally
{
if (f != null)
f.setAccessible(accessible);
@@ -317,11 +341,17 @@
public ConversionScore conversionScore(Class<?> cls)
{
if (cls.equals(value.getClass()))
+ {
return ConversionScore.exact;
+ }
else if (cls.isAssignableFrom(value.getClass())
|| cls.equals(Object.class))
+ {
return ConversionScore.compatible;
+ }
else
+ {
return ConversionScore.nomatch;
+ }
}
}