Java Moods

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Thursday, 17 September 2009

Spring: Use Custom Namespaces!

Posted on 23:30 by Unknown

Have you ever heard of custom XML namespaces for Spring? I know you love Spring (like I do), so... probably yes. They are available since Spring 2.0 which came out October 2006, so I just can't believe we didn't use them up to now.

The Old-Fashioned Way

Well, we are building our web apps on JSF and Spring Web Flow, and additionally use a custom framework for adding a few more features like mapping between business objects and view objects based on XML mapping descriptions. Of course, this framework part is designed "IoC friendly", i.e. it's based on interfaces and standard implementations that need to be plugged by Spring configuration.

We did this by providing a basic Spring configuration that defines defaults for most elements and injects all required references into the main configuration objects. To allow the project to provide custom implementations, this code relies on particular bean names that have to be defined by the custom project. Here's a simple example for the framework's configuration:

<bean id="iplIntegrationInfo" class="...IntegrationInfo">
<!-- myViewObjAccessor: to be defined in project specific Spring config file -->
<property name="viewObjAccessor" ref="myViewObjAccessor" />
<!-- myContextResolver: to be defined in project specific Spring config file -->
<property name="contextResolver" ref="myContextResolver" />
...
</bean>

<!-- These can be used for aliases if standard implementation should be used -->
<bean id="defaultViewObjAccessor" class="..." />
<bean id="defaultContextResolver" class="..." />

As you can see, all references are injected into the main configuration (iplIntegrationInfo). However, the referenced beans are not actually defined but have to be provided by the project. So, here's an example for the project's configuration:

<!-- use default -->
<alias alias="myViewObjAccessor" name="defaultViewObjAccessor" />

<!-- use custom implementation -->
<bean id="myContextResolver" class="..." />

Here we use the default for the first bean (by just establishing an alias for the configuration done in the framework file), and a custom implementation for the second.

This approach works, but obviously has a few drawbacks:

  • Configuration is shared between framework and project specific configuration code.
  • Project needs to know the framework's Spring file to do its work.
  • Internal framework structures (bean names, classes) are exposed to the outside.
  • A lot of XML code is required, even if using all the defaults.

Using Custom Namespaces

What should I say, we have switched to custom namespace lately and now configuration looks like this:

<ui:view-config/>

That's as short as it can be, but still is a complete configuration in case the project is using default implementations for all the beans. If the project would like to override some settings, the configuration file may be:

<ui:view-config>
<ui:viewobj-accessor ref="viewObjAccessor"/>
<ui:context-resolver ref="contextResolver"/>
</ui:view-config>

<bean id="viewObjAccessor" class="..." />
<bean id="contextResolver" class="..." />

Hence, you have the option to override all default implementations, and use meaningful tags to do so. Can you see the gains?

How Does This Magic Work?

I'm not going to provide full description on how to author custom namespaces since that is available in the Spring reference documentation and elsewhere. So, just a few basics to give you the idea...

First of all, you have to provide an XML schema describing your namespace. Then you have to implement a Namespace Handler that links each tag of your namespace to an XML parser, the Bean Definition Parser. And then, of course, those parsers must be implemented.

Each bean defintion parser is supposed to parse the XML element (including all attributes and sub elements) and to build the appropriate Spring beans. Spring provides a small hierarchy of classes you can use, depending on your situation:

  • The most specific is AbstractSimpleBeanDefinitionParser that fits well when there is a strong correlation between the attributes on a tag and the properties on your bean. In this case, there is really few code on your side.
  • The AbstractSingleBeanDefinitionParser is a bit more general, it allows you to create any single bean definition for an arbitrary complex nested XML structure. This involves more coding, of course, but still does some work for you (like automatically registering the bean in the context). This is the one you'll probably use most of the time.
  • The AbstractBeanDefinitionParser is even more general and allows you to create multiple bean definitions and register them directly. It takes care of id generation and a few other things.
  • Instead of using the latter one, you could also implement the BeanDefinitionParser interface directly, giving you all the flexibility you need.

All in all, you'll need a few hours to get comfortable with all the classes that are used to build up the bean definitions (DomUtils, BeanDefinition, BeanDefinitionBuilder, RuntimeBeanReference and ManagedMap/ManagedList to name a few).

But after that, building the parser and creating/registering your beans is quite straightforward. Moreover, you always can sneak a peek on how Spring itself is doing it for the Spring provided custom namespaces (like for Spring Security, for instance).

Okay, that's all for now, so go ahead and make life easier for your customers, your team, or yourself by providing a well-designed custom Spring namespace!

Read More
Posted in Spring | No comments

Tuesday, 8 September 2009

Spring: Test Framework Never Heard of Web Apps?

Posted on 02:31 by Unknown
Do you know the Spring TestContext Framework? You really should. It drastically simplifies JUnit-testing of Spring powered applications. One particular cool thing is that it offers an easy, annotation based way to load your Spring context and auto-wire your beans. For example, this is how it could look like for JUnit 4:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-config/ui-test-config.xml")
public class MyParticularTest {
@Autowired
private Controller controller;
...
}

This is really nice, but... there is one thing we stumbled upon lately.

The test framework by default is using the GenericXmlContextLoader which loads the Spring application context as an instance of GenericApplicationContext. This class, obviously, is not aware of web applications that would require a WebApplicationContext instead. Hence, you can't access any web related resources, use associated scopes etc.

Don't get me wrong... Spring TestContext Framework is nice, but it's more than strange that it does not support the web scenario. There is a Jira issue for that, but it's still open for more than 10 months now, and is scheduled not until Spring 3.1?!? That's just annoying.

Well, there are some workarounds of course, based on using a custom context loader. See this blog post or this Spring community thread, for instance.

Read More
Posted in JUnit, Spring, Testing | No comments

Highlight your Syntax

Posted on 00:53 by Unknown

Now, summer is nearly over and I'm back on this blog. During summer time, I use to spend more time with my family (and doing vacation ;-) but now my head is full with lots of snippets that could make it into this blog.

First of all, I have integrated some syntax highlighting to these pages. This might be well-known and boring for you, but I didn't really know how to do this until finding Alex Gorbatchev's SyntaxHighlighter. It's purely based on JavaScript and hence can be easily integrated with lots of products, tools and engines – like Blogger.com. Integration couldn't be easier, see here for a step-by-step explanation.

When adding code, you just have to give your <pre> element a class like this: <pre class="brush:java">. That's it!

What do you get by this? Well, the well-known, nicely formatted code blocks like this one

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
// Check that lookup methods exists.
MethodOverrides methodOverrides = getMethodOverrides();
if (!methodOverrides.isEmpty()) {
for (Iterator it = methodOverrides.getOverrides().iterator(); it.hasNext(); ) {
MethodOverride mo = (MethodOverride) it.next();
prepareMethodOverride(mo);
}
}
}

This works for lots of languages (called "brushes"), including XML and JavaScript, and you can easily provide a custom brush. Standard layout can be customized, of course, but the default is pretty good IMO.

There are just two or three things (there is always room for improvements ;-)

  • Syntax Highlighter documentation is a bit sparse...
  • The server hosting the CSS and JavaScript files, http://alexgorbatchev.com, seems to be not the fastest one. To speed up things, the Syntax Highlighter files could be hosted somewhere else, and they most probably already are.
  • You can highlight particular lines using the <pre class="brush:java; highlight: [14, 15]"> syntax (see line 7 in example above). However, it seems you can't specify areas but have to list all individual lines which might be cumbersome.

All in all, pretty cool. Syntax Highlighter is open source under LGPL 3, but the author asks you to "buy him a beer" if you use his tool. Well, I honestly will think of some donation ;-)

Read More
Posted in | No comments
Newer Posts Older Posts Home
Subscribe to: Comments (Atom)

Popular Posts

  • Eclipse: User Operation is Waiting, and Waiting, ...
    I am using Eclipse since quite a long time, sometimes around 2002. That was version 2.0, if I remember correctly. Since then, I have always ...
  • Maven Setting for Using a Single Repo Manager
    In a previous post I have tried to explain why it's a good idea to define your Maven repository in your settings.xml file instead of t...
  • Maven Plugins: Current Versions
    Upgrading Maven Plugins In preparation for a later switch to Maven 3 (which is already knocking on the door ) as well as to get rid of some ...
  • Maven Profiles: Activation... or not
    I love Maven. Really, I do. I should say that since this is my first post in my own blog (I know, I'm probably the last man on the plane...
  • Maven Documentation: The Missing List
    A rather weak talent of Maven is probably its documentation. This is my personal opinion, but it seem to match what other people think . Y...
  • Maven Plugins: Upgrade with Care!
    Upgrading Maven Plugins: Tips and Issues After having shown the list of current Maven plugin versions in my previous post , now I'm goin...
  • DocBook with Maven Issue
    We are using DocBook for writing technical documentation for all our projects and in-house frameworks. We are actually quite happy with thi...
  • Maven Plugin Releases: Do it yourself!
    In my previous post , I have complained about Maven plugins that do not release new versions although there are blocking issues that are rep...
  • Maven Compromised by Plugins
    Every piece of software has its flaws... The important part is how the project is dealing with bugs. Maven is fine With Maven, the situation...
  • Maven Enforcer Plugin: cool and annoying
    As a Maven expert, you probably have heard of maven-enforcer-plugin , "The Loving Iron Fist of Maven", as they say. It's so co...

Categories

  • BestPractices
  • Cargo
  • Checkstyle
  • Eclipse
  • Google
  • Hudson
  • Java
  • JBoss
  • JEE
  • Jenkins
  • JUnit
  • Maven
  • Nexus
  • oAW
  • Optimization
  • OSGi
  • Performance
  • Profiles
  • QA
  • Size
  • Spring
  • Testing
  • Tools
  • WebApp
  • Windows

Blog Archive

  • ►  2011 (5)
    • ►  May (1)
    • ►  April (1)
    • ►  March (2)
    • ►  February (1)
  • ►  2010 (11)
    • ►  October (2)
    • ►  September (1)
    • ►  April (1)
    • ►  March (1)
    • ►  February (4)
    • ►  January (2)
  • ▼  2009 (30)
    • ►  December (3)
    • ►  November (4)
    • ►  October (2)
    • ▼  September (3)
      • Spring: Use Custom Namespaces!
      • Spring: Test Framework Never Heard of Web Apps?
      • Highlight your Syntax
    • ►  June (4)
    • ►  May (5)
    • ►  April (4)
    • ►  March (5)
Powered by Blogger.

About Me

Unknown
View my complete profile