All 9 entries tagged Spring

View all 45 entries tagged Spring on Warwick Blogs | View entries tagged Spring at Technorati | There are no images tagged Spring on this blog

February 03, 2006

Interesting little problem upgrading to Spring 2.0M2 :)

Details here:

link

Essentially I upgraded my project from Spring 1.2.4 to Spring 2.0M2. Despite the addition of org.springframework.web.servlet.View#getContentType(); the upgrade appeared to be very smooth. The extensive unit tests passed, and all appeared to be well…..until I deployed it :)


14:50:36,676 ERROR [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'siteBuilderDAO' defined in ServletContext
resource [/WEB-INF/persistence-context.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessio
nFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFact
ory' defined in ServletContext resource [/WEB-INF/persistence-context.xml]: Cannot create inner bean 'uk.ac.warwick.sbr.hibernate.
ClassFilteringLoadEventListener#159f498' while setting bean property 'eventListeners' with key [post-load]; nested exception is or
g.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uk.ac.warwick.sbr.hibernate.ClassFilteringLo
adEventListener#159f498' defined in ServletContext resource [/WEB-INF/persistence-context.xml]: Instantiation of bean failed; nest
ed exception is java.lang.IllegalStateException: BeanWrapper does not hold a bean instance
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext
resource [/WEB-INF/persistence-context.xml]: Cannot create inner bean 'uk.ac.warwick.sbr.hibernate.ClassFilteringLoadEventListener
#159f498' while setting bean property 'eventListeners' with key [post-load]; nested exception is org.springframework.beans.factory
.BeanCreationException: Error creating bean with name 'uk.ac.warwick.sbr.hibernate.ClassFilteringLoadEventListener#159f498' define
d in ServletContext resource [/WEB-INF/persistence-context.xml]: Instantiation of bean failed; nested exception is java.lang.Illeg
alStateException: BeanWrapper does not hold a bean instance
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'uk.ac.warwick.sbr.hibernate.ClassFiltering
LoadEventListener#159f498' defined in ServletContext resource [/WEB-INF/persistence-context.xml]: Instantiation of bean failed; ne
sted exception is java.lang.IllegalStateException: BeanWrapper does not hold a bean instance
java.lang.IllegalStateException: BeanWrapper does not hold a bean instance
        at org.springframework.util.Assert.state(Assert.java:341)
        at org.springframework.beans.BeanWrapperImpl.getPropertyDescriptorInternal(BeanWrapperImpl.java:274)
        at org.springframework.beans.BeanWrapperImpl.getPropertyType(BeanWrapperImpl.java:323)
        at org.springframework.beans.PropertyEditorRegistrySupport.findCustomEditor(PropertyEditorRegistrySupport.java:233)
        at org.springframework.beans.PropertyTypeConverter.doTypeConversionIfNecessary(PropertyTypeConverter.java:100)
        at org.springframework.beans.PropertyTypeConverter.doTypeConversionIfNecessary(PropertyTypeConverter.java:73)
        at org.springframework.beans.PropertyTypeConverter.convertToTypedMap(PropertyTypeConverter.java:277)
        at org.springframework.beans.PropertyTypeConverter.doTypeConversionIfNecessary(PropertyTypeConverter.java:131)
        at org.springframework.beans.BeanWrapperImpl.doTypeConversionIfNecessary(BeanWrapperImpl.java:853)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doTypeConversionIfNecessary(AbstractBeanFactory.java:672)

        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:370)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:126)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapabl
eBeanFactory.java:542)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFact
ory.java:368)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBeanDefinition(BeanDefinitionValueRes
olver.java:151)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolv
er.java:97)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.jav
a:235)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolv
er.java:118)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapabl
eBeanFactory.java:764)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFa
ctory.java:575)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFact
ory.java:405)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:238)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:148)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java
:186)
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolv
er.java:106)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapabl
eBeanFactory.java:764)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFa
ctory.java:575)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFact
ory.java:405)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:238)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:148)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactor
y.java:253)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:331)
        at org.springframework.web.context.support.AbstractRefreshableWebApplicationContext.refresh(AbstractRefreshableWebApplicat
ionContext.java:155)
        at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:240)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:178)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)

was thrown up. OK, I thought; lets look at the class in question (bear in mind this has all been working previously ;)):

The constructor looked like:


    public ClassFilteringLoadEventListener(final Map> theListeners) {
        }
    }

And it was being wired up:


  >bean class="uk.ac.warwick.sbr.hibernate.ClassFilteringLoadEventListener"<
            >constructor-arg index="0"<
              >map<
                >entry key="uk.ac.warwick.sbr.linksgenerator.SiteNavigationContentFetcher"<
                  >list<
                    >bean class="uk.ac.warwick.sbr.hibernate.AutoWiringLoadedObjectListener"/<
                  >/list<
                >/entry<
        >/map<
    >constructor-arg<
>/class<

Hmm, nothing strange there either (apart from me getting my < and > mixed up ;))

And then it occurred to me that Spring 2.0M2 understands generics :) Modifying the constructor argument to take a non typed Map fixed the problem.

Very subtle; took me most of the afternoon to catch this one ;)

JIRA is here: link

All this is redundant anyway because I found SWF (Spring Web Flow) PR5 uses a few classes which have been moved (PropertyEditorRegistrar etc.)


February 02, 2006

Anyone know of a Composite proxy?

Any one know of such a beast:
link

I could write one, but why write your own when you can butcher others ….


December 16, 2005

Interesting article on threadLocals

Writing about web page http://blog.arendsen.net/index.php/2005/02/22/threadlocals-and-memory-leaks-revisited/

link

Very good.


December 12, 2005

How to post process a Spring Bean?

So I have a FactoryBean which produces a FreeMarker configuration and it all works well.

Now I wanted to precompile all the freeMarker templates and started looking for the appropriate Springs infrastructure to tie into.

I came up with the following options:
[extend the existing BeanFactory
This just seemed hacky. I wasn't changing the strategy for loading the object so the factoryness hadn't changed.

[implement a BeanPostProcessor
This looked like promising; it executed after the factory had done it's thing and had a very convenient "postProcessAfterInitialization" method which passed in the name of the bean, and the bean itself. Cool. The problem is that the bean is the original beanFactory. Sure, I could call getObject() but it all started to feel a bit fragile and icky

[implement BeanFactoryPostProcessor
This went out of the window for two reasons; it suffers the same "problem" as BPP (not a "problem" with Spring, just the way I want to use it) and the single "postProcessBeanFactory" is called before the beans are realised (or instantiated as Spring prefers).

at this point I was thinking, surely there must be something more :)

and there is

[implement ApplicationListener
This little gem (thanks Dave Hewitt :)) listens to all the various events that hook in very nicely with the lifecycle of a BeanFactory, so there is a ContextClosed, ContextRefreshed and RequestHandled event. Implementing the single method "onApplicationEvent" which passed in the ApplicationEvent meant I could write the following bean:


public final class FreeMarkerCompilerEventListener implements ApplicationListener {
    private static final Logger LOGGER = Logger.getLogger(FreeMarkerCompilerEventListener.class);
    private final File templateDir;
    private final Configuration configuration;

    public FreeMarkerCompilerEventListener(final Configuration theConfiguration, final Resource theResource) {
        this.configuration = theConfiguration;
        this.templateDir = verifyResource(theResource);
    }

    public void onApplicationEvent(final ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            compile();
        }
    }

    private File verifyResource(final Resource resource) {
        File file;
        try {
            file = resource.getFile();
        } catch (final IOException e) {
            throw new IllegalStateException("Resource " + resource + " must be a directory!", e);
        }

        if (!file.isDirectory()) {
            throw new IllegalStateException("Resource " + resource + " must be a directory!");
        }

        return file;
    }

    private void compile() {
        String[] templateNames = getTemplateNames();
        for (String name: templateNames) {
            try {
                LOGGER.info("Precompiling freemarker template [" + name + "]");
                configuration.getTemplate(name);
            } catch (final IOException e) {
                throw new IllegalStateException("Cannot get template for " + name, e);
            }
        }
    }

    private String[] getTemplateNames() {
        List files = new ArrayList();
        for (File file: templateDir.listFiles()) {
            findFreeMarkerTemplates(file, "", files);
        }
        return files.toArray(new String[] {});
    }

    private void findFreeMarkerTemplates(final File root, final String parentPath, final List filesFound) {
        if (root.isDirectory()) {
            for (File file: root.listFiles()) {
                String newParentPath = parentPath;
                if (StringUtils.hasLength(newParentPath)) {
                    newParentPath += "/";
                }
                newParentPath += root.getName();
                findFreeMarkerTemplates(file, newParentPath, filesFound);
            }
        } else {
            if (root.getName().toLowerCase().endsWith(".ftl")) {
                filesFound.add(parentPath + "/" + root.getName());
            }
        }
    }
}

No messing around with BeanFactories, or fragile bean lookups by name, I simply wire this :


 <bean id="freeMarkerConfig" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
   <property name="templateLoaderPath"><value>/WEB-INF/freemarker/</value></property>
 </bean>

  <bean id="freeMarkerCompiler" class="uk.ac.warwick.sbr.freemarker.FreeMarkerCompilerEventListener">
    <constructor-arg index="0" ref="freeMarkerConfig"/>
    <constructor-arg index="1" value="/WEB-INF/freemarker/"/>
  </bean>

Spring will realise (via the proper use of it's BeanFactoryPostProcessor) that I have defined an ApplicationListener and will automatically call it when an ApplicationEvent is fired.

Cool.


November 22, 2005

Excellent spring related web site

Writing about web page http://www.springhub.com/

cool.

spring container + inner beans

Writing about web page http://www.springframework.org/docs/api/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.html

So I recently had to wire up some spring managed beans with some constants. ….and I hadn't the foggiest on how to do it :)

Perusing the forums and the spring documentation, I found this little beauty

The problem is that you are not creating a new instance of the constant, you are merely referencing that constant, so the usual
<bean id="uk.yourcompany.class.CONSTANT"/>
wouldn't work because you are asking spring to instantiate a new instance. You must do
<bean id="uk.yourcompany.class.CONSTANT" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>

To reference it, simply do

<bean id="yourBean" class="uk.yourcompany.class.SomeBean">
  

On a related note, if you do want to instantiate an inner class (so long as it is public), you cannot do

<bean id="yourBean" class="uk.yourcompany.class.OuterClass.InnerClass"/>

you must do

>bean id="yourBean" class="uk.yourcompany.class.OuterClass$InnerClass"/>

HTH.


September 23, 2005

MVC Views; how stupid should they be

It seems to me that a lot of people are not utilising the full power of the "view" concept of the MVC paradigm.

For example, imagine a scenario where you want to render one page for logged in users or another for logged out users. Should this logic go in the controller, or the view? It seems the gut reaction is to put it into the controller, which I think is wrong :)

Controllers should be doing business logic, with complete disregard for how it is rendered. Controllers should not know whether they are returning html, rss etc. Of course this is naieve and it may well be that different models are required, in which case the controller has to know, but in the main, keep those MVC boundaries!

In the readonly/readwrite view example, I typically have a delegating view:


public final class PagePermissionsView implements View {
    private View readView;
    private View editView;

    public void render(
            final Map model,
            final HttpServletRequest request,
            final HttpServletResponse response) throws Exception {
        ServletRequestAttributeAccessor accessor = new 
        boolean userLoggedIn = ….
        if (userLoggedIn) {
            editView.render(model, request, response);
        } else {
            readView.render(model, request, response);
        }
    }

    public void setEditView(final View detailsView) {
        this.editView = detailsView;
    }

    public void setReadView(final View simpleView) {
        this.readView = simpleView;
    }
}

This keeps view related logic firmly in the view.

Same with complicated reports. If you need to group data, a lot of developers will perform that grouping in the controller. I would rather do that in the jsp and utilise tag libraries to perform the data, for example, I very often have need of a tag which will take in a collection and return a map, where the key is the value of a property, and the value in the map is a collection of all the objects that matched.

I know exactly why developers are "afraid" to put logic into views, and that is because of the horror that was pre MVC :) But there is a difference between business logic and view logic.

A useful yardstick for any "where should this go" question is "if I need to change how this works, which layers would I need to change". If I decide to change how the view is rendered, I want to change the view, not the controller :)

Rant over; let the flames being…..


September 21, 2005

Spring web flow progresses :)

Writing about web page http://jroller.com/page/kdonald?entry=web_flows_as_application_modules

About pigging time Keith :)

Now hurry up and release it :)


September 16, 2005

Interesting blog

Writing about web page http://www.jroller.com/page/sdevijver?entry=processing_e_mail_messages_with


September 2021

Mo Tu We Th Fr Sa Su
Aug |  Today  |
      1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30         

Search this blog

Tags

Galleries

Most recent comments

  • Interesting… While I'm not completely convinced in such microbenchmarks, I'm pretty sure that 1ms … by Alexander Snaps on this entry
  • Hello. I bought the book yesterday. I was trying to find the source code for chapter 11 and chapter … by Suleman on this entry
  • http://woosight.net/account/login?username=demo by live mashup demo on this entry
  • Thanks mate ….. This blog was really helpful. by Maaz Hurzuk on this entry
  • Ty. Not directly helpful for my problem, but pointed me in the right direction. You will also get th… by Mike E. on this entry

Blog archive

Loading…
RSS2.0 Atom
Not signed in
Sign in

Powered by BlogBuilder
© MMXXI