While somewhat related, that isn't really what I had in mind.  Transactions 
shouldn't go on action beans anyway, what if you replace stripes with something 
else?  All business logic & transactions should go into reusable objects that 
aren't so tightly coupled to some library.  But that is another subject....

I have a SecurityInterceptor that has a few spring managed dependencies (user 
manager, emailer, etc).  When I put the class name as an interceptor in 
web.xml, the stripes configuration simply calls class.newInstance() to 
construct a plain vanilla version of it.  I think we can do a little better 
than that if we made all calls to class.newInstance() go through a configurable 
component.  That way, when stripes goes to instantiate my interceptor, I could 
override that and pull it out of the spring context instead.  The same for 
action beans:

    protected ActionBean makeNewActionBean(Class<? extends ActionBean> type, 
ActionBeanContext context)
        throws Exception {

        return type.newInstance();
    }

(looks like the context param can be removed unless it intended for 
subclasses)..

But if we replaced that with configuration.getInstiantator().newInstance(type); 
I could have an action bean like

class UserAction implements ActionBean  {

private UserManager userManager;
public void setUserManager(UserManager userManager)  {
            this.userManager = userManager;
      }
}

<bean id="userAction" class="com.test.web.UserAction">
      <property name="userManager" ref="userManager" />
</bean>

And I could remove the spring interceptor and just use normal DI like the rest 
of the application.  Not just for action beans either, any class that stripes 
calls newInstance on could potentially be pulled out of spring, guice, or ejb, 
whatever.  We have a whole set of stripes components that we've hacked around 
the configuration to make work with spring.  The interceptors are particularly 
hackish...




From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Chris Herron
Sent: Thursday, May 15, 2008 11:21 AM
To: Stripes Users List
Subject: Re: [Stripes-users] Idea regarding use of class.newInstance() and 
spring integration

John,

I've looked into doing something like this specifically for ActionBeans. In my 
case, I wanted to use various Spring annotations (security, transaction) on my 
ActionBean event handler methods. In a nutshell, I extended Stripe's 
NameBasedActionResolver to fetch ActionBean instances from Spring.

Some of the issues I encountered:

* For Spring-managed ActionBeans, you can't use JDK dynamic proxies, because 
DP's require an interface to hide behind. Instead, I used CGLib proxies. With 
CGLib proxies, the ActionBean needs to be registered with Stripes twice; Once 
under the original class name, and again under the CGLib descendant class name 
e.g.
- com.foo.ExampleActionBean and...
- com.foo.ExampleActionBean$$EnhancerByCGLIB$$515e0936

* Creating explicit Spring XML config for lots of objects is a real bitch - and 
if you're a Stripes fan you'll probably want to stay away from that. My 
approach dynamically created Spring-managed ActionBeans in the Spring context. 
This worked fine until I switched to using Spring's WebApplicationContext. The 
Spring WebApplicationContext doesn't allow you to programmatically define 
beans. Bah.

In the end I shelved this work because I was doing fine without those 
annotations at the ActionBean level. Below is my original implementation of a 
Spring ActionResolver. Hope this helps.

Chris.

/**
 * Instantiates Stripes ActionBeans by programmaticially defining a Spring bean.
 * This is preferable to defining every Stripes ActionBean in the application
 * context XML config. The main reason for doing this is to leverage Spring
 * interceptors for things like security. Note that because action beans are not
 * usually accessed via interfaces, CGLib proxies must be used instead of JDK
 * dynamic proxies. To do this, must have the following config in your Spring
 * application context XML:
 * <aop:config proxy-target-class="true"/>.
 * Beware that CGLib proxies have certain limitations (e.g. cannot proxy methods
 * marked as final).
 *
 * @author cherro
 */
public class SpringActionResolver extends NameBasedActionResolver {
    /** Tracks the ActionBeans that have already been defined in Spring. */
    private Set<String> processedBeanNames = new HashSet<String>();

    /** [EMAIL PROTECTED] */
    @Override
    protected ActionBean makeNewActionBean(
            Class<? extends ActionBean> type,
            ActionBeanContext actionBeanContext)
            throws Exception {
        final String beanName = type.getName();
        if (!processedBeanNames.contains(beanName)) {
            GenericApplicationContext springContext =
                    SpringUtil.getInstance().getContext();
            BeanDefinition beanDefinition = new RootBeanDefinition(type);
            beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
            springContext.registerBeanDefinition(beanName, beanDefinition);
            ActionBean proxied =
                    (ActionBean) SpringUtil.getInstance().getContext()
                            .getBean(beanName, type);

            // The CGLib proxy has a different class name (because it is a
            // subtype of the proxied class). So, we need to register the new
            // class in order to configure its event mappings.
            super.addActionBean(proxied.getClass());
            processedBeanNames.add(beanName);
            return proxied;
        } else {
            return (ActionBean) SpringUtil.getInstance().getContext()
                    .getBean(beanName, type);
        }
    }
}


On May 15, 2008, at 10:47 AM, Newman, John W wrote:


Hi,

I'd like for my application specific extensions to stripes (type converters, 
interceptors, even action beans, etc) to be pulled out of the spring context.  
I've managed to do this somewhat by providing my own Configuration, but the 
implementation is far from ideal.  So I was thinking everywhere stripes calls 
class.newInstance(), could that be replaced by instantiator.newInstance(), 
where instantiator is a configurable component to provide new instances of a 
given class...

For example,

interface Instantiator {

      <T> T newInstance(Class<T> clazz) throws InstantiationException,
                  IllegalAccessException;
}


class DefaultInstantiator implements Instantiator {

      public <T> T newInstance(Class<T> clazz) throws InstantiationException,
                  IllegalAccessException {
            return clazz.newInstance();
      }
}


class SpringInstantiator extends DefaultInstantiator {

      @Override
      public <T> T newInstance(Class<T> clazz) throws InstantiationException,
                  IllegalAccessException {
            T bean = SpringUtil.getInstance().getBean(clazz);
            if (bean != null) {
                  return bean;
            }
            return super.newInstance(clazz);
      }
}

That would offer much better integration between stripes and spring / other DI 
frameworks.  This could also eliminate the @SpringBean annotation and allow 
action beans to use normal setter injection.  Thoughts?

-John
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/_______________________________________________
Stripes-users mailing list
[email protected]<mailto:[email protected]>
https://lists.sourceforge.net/lists/listinfo/stripes-users

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft 
Defy all challenges. Microsoft(R) Visual Studio 2008. 
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Stripes-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-users

Reply via email to