Blog

Setting session bean property in SeamTest

17 Apr, 2009
Xebia Background Header Wave

SeamTest is a class we extend for the tests we write in our Seam application. It provides the seam environment in tests something analogous to WicketTester in Wicket Application.
I want to share some information on setting the property of Session bean, i came to know while using the SeamTest.

Let us look at the following code.

@Stateless
@Scope(ScopeType.SESSION)
@Name("Something")
public class SomethingBean implements Something {
    @Logger
    private Log log;
    @In
    StatusMessages statusMessages;
    @In
    User user;
    @In
    public String test;
    @Out
    boolean invoked = false;
    @Out
    String userName = "No name";
    public String something() {
        log.info("Something.something() action called");
        statusMessages.add("something");
        invoked = true;
        userName = user.getName();
        return test;
    }
}

And the testClass :

public class SomethingTest extends SeamTest {
    @Test
    public void test_something() throws Exception {
        new FacesRequest() {
            @Override
            protected void invokeApplication() {
                setValue("#{user.name}", "user");
                setValue("#{Something.test}", "testValue");
        //      Contexts.getSessionContext().set("test", "testValue");
                Object result = invokeMethod("#{Something.something}");
                Object object = Contexts.getSessionContext().get("invoked");
                Assert.assertTrue((Boolean) object);
                    Assert.assertEquals(Contexts.getSessionContext().get("userName"), "user");
                Assert.assertEquals(result, "testValue");
            }
        }.run();
    }
}

Using the setValue() method of the SeamTest, we can set the property on Entity bean User. BUT when I tried to use the SetValue() method to set the ‘test’ property on ‘Something’ (Session bean ) I get the following stack trace.
java.lang.AssertionError: javax.el.PropertyNotFoundException: The class ‘org.javassist.tmp.java.lang.Object_$$_javassist1′ does not have the property ‘test’.
at org.jboss.seam.mock.AbstractSeamTest$Request.onException(AbstractSeamTest.java:455)

Clearly Seam is trying to find the ‘test’ property on some other class "org.javassist.tmp.java.lang.Object
$$_javassist_1".
This is the proxy class generated by Seam framework. The proxy class has the same interface as the the Session bean ‘Something’. It doesn’t have the property ‘test’, since the interface doesn’t declare the getter and setter.
The Entity bean ‘user’ is handled differently by the Seam framework: No proxy is created, thus the property can be set using

 setValue("#{user.name}", "user");

So if in test we cannot set the property like this for session bean, how does Seam set this in production?
Seam looks for the @In property in the corresponding Context if the property is not not specified. and if it is there in the context, it is set.
The solution is to set the property value to corresponding Context.
For example in your Seam Test you could use,

Contexts.getSessionContext().set("test", "testValue").

The other option can be to have the getter and setter for the property in the @Local Interface implemented by the Session bean. This way the getter and setter of the property is there in the proxy class generated and we can use ,
setValue(Something.test, "testValue") to set the property from test. But this would break the injection of the property. The property wont be looked up in the context and we get the error "@In attribute requires non-null value: Something.test"
In some scenarios where property is not annotated with @In, then we can go for the previous option.

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts