Maven, GWT and ECJ

When compiling a GWT webapp with the GWT Maven Plugin, you might encounter an exception such as

java.lang.NoSuchFieldError: warningThreshold

The reason is having ECJ in your classpath with a version different from what GWT includes. Unfortunately, GWT’s version is not repackaged and thus clashes with other versions. The quick fix is setting the gwtSdkFirstInClasspath configuration option for the gwt-maven-plugin (available since 2.1.0-1, see this issue):

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>gwt-maven-plugin</artifactId>
  <version>2.1.0-1</version>
  <configuration>
    ...
    <gwtSdkFirstInClasspath>true</gwtSdkFirstInClasspath>
  </configuration>
Posted in Eclipse, Java, Maven | 6 Comments

Tomcat not reloading Vaadin App’s View when running in Eclipse

Ever had the problem that changes to a Vaadin App’s UI were not reflected in the runtime when running and deploying to a Tomcat in Eclipse, even after reloading the app? Vaadin stores views in the Session, and a default Tomcat installation will use a persistent Session Manager. Sessions are recreated after the app has been reloaded when using the same browser with the same session key, and the stale view will be loaded from the session.

The solution is simple: In your context.xml (either in Tomcat’s conf dir, or in the Servers project in Eclipse), locate these lines and do what they say:

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
Posted in Eclipse, Java, Vadiin | Leave a comment

Eclipse Plugin for Concordion

I’ve released a new Eclipse Plugin for editing Concordion Specifications. Concordion is a cool integration testing framework, check out the tutorial if you’re new to Concordion.

The plugin can be installed from the update site as described on the Project Page on Google Code. A good way to keep up-to-date on new plugin releases is to follow the Ohloh Journal, source code is in the Repo on github.

Posted in Concordion, Eclipse, Java, Testing | Leave a comment

Adding Plug-Ins To Your Application With Spring

Spring’s classpath scanning support can be leveraged to easily implement an application that supports plugins to be added.

One method would be to simply scan a specific package (for example org.example.myapp.plugin for beans annotated with @Component, and add them to your application context. This has some disadvantes though:

  • If plugins use annotation-based dependency injection internally, that might clash with your context as all plugin beans will end up in your application’s context
  • It is a very unspecific way to load plugin classes. You’ll need to document very thoroughly what kind of plugin interface your application provides.

It’s probably a better idea to provide a specific interface for your extension points, and then allow plugins to implement them. In this article, I’ll describe a way to achieve this with Annotations and Spring. Suppose your extension point interface looks like this:

public interface ProviderPlugin {
    Resource provide();
}

The class PluginLoader introduced below will then allow you to implement your plugin like this:

@MyAppPlugin
public class MyProviderPlugin implements ProviderPlugin {
    public Resource provide() { ... }
}

As you can see, all plugins are annotated with a specific annotation, and implement one or more of the extension point interfaces. A plugin annotation is meta-annotated with Spring’s @Component, which allows us to discover and instantiate the plugin using classpath-scanning and a Spring application context.

@Component
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface MyAppPlugin {
}

The PluginLoader class contains the plugin lookup and instantiation logic. It is parametrized with the plugin annotation type and the base package to search for plugins:

public class PluginLoader {
    private final Class<? extends Annotation> pluginAnnotationType;
    private final String pluginBasePackage;
    private ListableBeanFactory context;

    /**
     * 
     * @param pluginAnnotationType The {@link Annotation} for plugin descriptor types
     * @param pluginBasePackage Base package to look in for plugins
     */
    public PluginLoader(Class<? extends Annotation> pluginAnnotationType, 
            String pluginBasePackage) {
        this.pluginAnnotationType = pluginAnnotationType;
        this.pluginBasePackage = pluginBasePackage;
    }

Most of the work is done in the loadContext() method. Here, all plugins annotated with your plugin annotation are instantiated into an AnnotationConfigApplicationContext:

    private void loadContext() {
        if (context == null) {
            // Create a parent context containing all beans provided to plugins
            // More on that below in the article...
            GenericApplicationContext parentContext = 
                new GenericApplicationContext(providedBeans);
            parentContext.refresh();

            // Create the annotation-based context
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
            context.setParent(parentContext);
            
            // Scan for classes annotated with @<PluginAnnotaionType>,
            // do not include standard Spring annotations in scan
            ClassPathBeanDefinitionScanner scanner = 
                new ClassPathBeanDefinitionScanner(context, false);
            scanner.addIncludeFilter(new AnnotationTypeFilter(pluginAnnotationType));
            
            scanner.scan(pluginBasePackage );
            context.refresh();
            
            this.context = context;
        }
    }

The method getPluginDescriptors() returns all plugin beans in the context that implement a specified interface:

    private static <T> Collection<T> getPluginDescriptors(ListableBeanFactory context,
            Class<T> pluginDescriptorType) {
        return context.getBeansOfType(pluginDescriptorType).values();
    }

The getPlugins() method will call loadContext() to find and instantiate all plugins if necessary, and return a collection of plugin instances:

    /**
     * Returns all plugins annotated with the annotation specified in the constructor,
     * and returns all instances having type T. This method can be called multiple times
     * for the same loader if you support multiple plugin descriptor types. The plugin
     * scan will be done only once.
     * 
     * @param <T> Plugin descriptor interface type
     * @param pluginDescriptorType Plugin descriptor interface class
     * @return A {@link Collection} of all plugins implementing the specified plugin interface type
     */
    public <T> Collection<T> getPlugins(Class<T> extensionPointType) {
        loadContext();
        return getPluginDescriptors(context, extensionPointType);
    }

What if your plugins require access to beans in the context they are loaded in? For example an application-provided DataSource, or some sort of resource manager? To achieve this, PluginLoader needs a provideBean() method that allows the hosting application to provide bean instances to plugins:

    /**
     * Provide beans available to plugins.
     * @param beanName Bean name
     * @param bean Instance
     */
    public void provideBean(String beanName, Object bean) {
        if (context != null) {
            throw new IllegalStateException(
                "provideBean must be called before loadContext/getPlugins");
        }
        providedBeans.registerSingleton(beanName, bean);
    }

Plugins can then reference these beans:

@MyPlugin
public class SomePlugin implements MyProviderPlugin {
    @Autowired @Qualifier("resourceManager") ResourceManager resourceManager;
    ...
}

Loading your plugins is as easy as:

    PluginLoader pluginLoader = new PluginLoader(MyPlugin.class);
    Collection<MyProviderPlugin> providers = 
        pluginLoader.getPlugins(MyProviderPlugin.class);

An example usage of the plugin loader would be to inject plugins into your application context somwhere along these lines:

@Configuration
public class MyAppConfiguration {
    ...
    @Bean
    public ProviderRepository providerRepository() {
        PluginLoader pluginLoader = new PluginLoader(MyPlugin.class);
        // Inject another bean reference into the plugin context
        pluginLoader.provideBean("resourceManager", resourceManager());
        Collection<MyProviderPlugin> providers = 
            pluginLoader.getPlugins(MyProviderPlugin.class);
        return new ProviderRepository(providers);
    }
    ...
}
Posted in Java, Spring | Leave a comment

Annotation-based Spring Configuration

Spring has been supporting annotation-based context configuration for some years now. Time to explore it if you haven’t already done so! A quick overview is available here. Getting rid of your XML configuration is as easy as:

@Configuration
public class MyContext {
    // Reference to a bean defined somewhere else
    @Autowired SomeBean someBean;

    @Bean
    public OtherBean otherBean() {
        return new OtherBean(someBean);
    }

    // A bean referencing another bean in this context
    @Bean AnyBean anyBean() {
        return new AnyBean(otherBean());
    }
}

If you need to reference a specific bean using @Autowired, you can use @Qualified to reference a bean by name:

    // Reference to a specific bean defined somewhere else
    @Autowired @Qualifier("someSpecificBean")
    SomeBean someBean;

Then, somewhere in your application’s bootstrap code, load the context. In a Web App, load the @Configuration-annotated class using a ContextListener as you would with a XML context configuration.

ApplicationContext context = new AnnotationConfigApplicationContext(MyContext.class);
context.refresh();

Another possibility is to use classpath scanning to pick up your annotated beans, contexts, controllers, …:

ApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("my.base.package");
context.refresh();

That’s it! You get a context configuration in pure Java source code that’s easy to navigate and refactor in any IDE of your choice.

If you want to load a context in a test case using @ContextConfiguration, you’ll have to resort to a custom ContextLoader implementation (see here) until SPR-6184 is fixed.

Posted in Java, Spring | 1 Comment

Scrollable GWT TabLayoutPanel

When writing a GWT app without using one of the more advanced widget toolkits, one limiting shortcoming is that the TabLayoutPanel does not allow the user to scroll invisible tabs into view when there are too many tabs to all fit into the width of the widget.

Here’ s a TabLayoutPanel that adds two scroll buttons in the upper left corner whenever the widget becomes too small to show all tabs. It works as a drop-in replacement for TabLayoutPanel. You won’t be able to use it directly in UiBinder due to an issue with parsing custom widget elements. The need for the scroll buttons is checked whenever the browser window is resized, or a tab is added or removed.

Update: See here for an updated version.

package com.gwtscrolledtablayoutpanel.ui;

import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A {@link TabLayoutPanel} that shows scroll buttons if necessary
 */
public class ScrolledTabLayoutPanel extends TabLayoutPanel {

        private static final int IMAGE_PADDING_PIXELS = 4;

        private LayoutPanel panel;
        private FlowPanel tabBar;
        private Image scrollLeftButton;
        private Image scrollRightButton;
        private HandlerRegistration windowResizeHandler;

        private ImageResource leftArrowImage;
        private ImageResource rightArrowImage;

        public ScrolledTabLayoutPanel(double barHeight, Unit barUnit,
            ImageResource leftArrowImage, ImageResource rightArrowImage) {
                super(barHeight, barUnit);

                this.leftArrowImage = leftArrowImage;
                this.rightArrowImage = rightArrowImage;

                // The main widget wrapped by this composite, which is a LayoutPanel with the tab bar & the tab content
                panel = (LayoutPanel) getWidget();

                // Find the tab bar, which is the first flow panel in the LayoutPanel
                for (int i = 0; i < panel.getWidgetCount(); ++i) {
                        Widget widget = panel.getWidget(i);
                        if (widget instanceof FlowPanel) {
                                tabBar = (FlowPanel) widget;
                                break; // tab bar found
                        }
                }

                initScrollButtons();
        }

        @Override
        public void add(Widget child, Widget tab) {
                super.add(child, tab);
                checkIfScrollButtonsNecessary();
        }

        @Override
        public boolean remove(Widget w) {
                boolean b = super.remove(w);
                checkIfScrollButtonsNecessary();
                return b;
        }

        @Override
        protected void onLoad() {
                super.onLoad();

                if (windowResizeHandler == null) {
                        windowResizeHandler = Window.addResizeHandler(new ResizeHandler() {
                                @Override
                                public void onResize(ResizeEvent event) {
                                        checkIfScrollButtonsNecessary();
                                }
                        });
                }
        }

        @Override
        protected void onUnload() {
                super.onUnload();

                if (windowResizeHandler != null) {
                        windowResizeHandler.removeHandler();
                        windowResizeHandler = null;
                }
        }

        private ClickHandler createScrollClickHandler(final int diff) {
                return new ClickHandler() {
                        @Override
                        public void onClick(ClickEvent event) {
                                Widget lastTab = getLastTab();
                                if (lastTab == null)
                                        return;

                                int newLeft = parsePosition(tabBar.getElement().getStyle().getLeft()) + diff;
                                int rightOfLastTab = getRightOfWidget(lastTab);

                                // Prevent scrolling the last tab too far away form the right border,
                                // or the first tab further than the left border position
                                if (newLeft <= 0 && (getTabBarWidth() - newLeft < (rightOfLastTab + 20))) {
                                        scrollTo(newLeft);
                                }
                        }
                };
        }

        /** Create and attach the scroll button images with a click handler */
        private void initScrollButtons() {
                scrollLeftButton = new Image(leftArrowImage);
                int leftImageWidth = scrollLeftButton.getWidth();
                panel.insert(scrollLeftButton, 0);
                panel.setWidgetLeftWidth(scrollLeftButton, 0, Unit.PX, leftImageWidth, Unit.PX);
                panel.setWidgetTopHeight(scrollLeftButton, 0, Unit.PX, scrollLeftButton.getWidth(), Unit.PX);
                scrollLeftButton.addClickHandler(createScrollClickHandler(+20));
                scrollLeftButton.setVisible(false);

                scrollRightButton = new Image(rightArrowImage);
                panel.insert(scrollRightButton, 0);
                panel.setWidgetLeftWidth(scrollRightButton, leftImageWidth + IMAGE_PADDING_PIXELS, Unit.PX, scrollRightButton.getWidth(), Unit.PX);
                panel.setWidgetTopHeight(scrollRightButton, 0, Unit.PX, scrollRightButton.getHeight(), Unit.PX);

                scrollRightButton.addClickHandler(createScrollClickHandler(-20));
                scrollRightButton.setVisible(false);
        }

        private void checkIfScrollButtonsNecessary() {
                // Defer size calculations until sizes are available, when calculating immediately after
                // add(), all size methods return zero
                DeferredCommand.addCommand(new Command() {
                        @Override
                        public void execute() {
                                boolean isScrolling = isScrollingNecessary();
                                // When the scroll buttons are being hidden, reset the scroll position to zero to
                                // make sure no tabs are still out of sight
                                if (scrollRightButton.isVisible() && !isScrolling) {
                                        resetScrollPosition();
                                }
                                scrollRightButton.setVisible(isScrolling);
                                scrollLeftButton.setVisible(isScrolling);
                        }
                });
        }

        private void resetScrollPosition() {
                scrollTo(0);
        }

        private void scrollTo(int pos) {
                tabBar.getElement().getStyle().setLeft(pos, Unit.PX);
        }

        private boolean isScrollingNecessary() {
                Widget lastTab = getLastTab();
                if (lastTab == null)
                        return false;

                return getRightOfWidget(lastTab) > getTabBarWidth();
        }

        private int getRightOfWidget(Widget widget) {
                return widget.getElement().getOffsetLeft() + widget.getElement().getOffsetWidth();
        }

        private int getTabBarWidth() {
                return tabBar.getElement().getParentElement().getClientWidth();
        }

        private Widget getLastTab() {
                if (tabBar.getWidgetCount() == 0)
                        return null;

                return tabBar.getWidget(tabBar.getWidgetCount() - 1);
        }

        private static int parsePosition(String positionString) {
                int position;
                try {
                        for (int i = 0; i < positionString.length(); i++) {
                                char c = positionString.charAt(i);
                                if (c != '-' && !(c >= '0' && c <= '9')) {
                                        positionString = positionString.substring(0, i);
                                }
                        }

                        position = Integer.parseInt(positionString);
                } catch (NumberFormatException ex) {
                        position = 0;
                }
                return position;
        }
}
Posted in Google Web Toolkit, Java | Tagged , , | 5 Comments

Mocking a multipart/form-data HTTP request in a unit test

If you have a servlet that processes HTML Form post data, you might want to simulate such a request in your unit tests. This is easily done with Apache Commons HttpClient using MultipartRequestEntity. This example uses MockHttpServletRequest from Spring, but can be easily modified for your needs in case you use another Servlet testing framework:

public void createMultipartFormDataRequest(MockHttpServletRequest request, String resourceName, String partName) throws IOException {
    // Load resource being uploaded
    byte[] fileContent = FileCopyUtils.copyToByteArray(
        getClass().getResourceAsStream(resourceName));
    // Create part & entity from resource
    Part[] parts = new Part[] {
        new FilePart(partName, new ByteArrayPartSource(resourceName, fileContent)) };
    MultipartRequestEntity multipartRequestEntity =
        new MultipartRequestEntity(parts, new PostMethod().getParams());
    // Serialize request body
    ByteArrayOutputStream requestContent = new ByteArrayOutputStream();
    multipartRequestEntity.writeRequest(requestContent);
    // Set request body to HTTP servlet request
    request.setContent(requestContent.toByteArray());
    // Set content type to HTTP servlet request (important, includes Mime boundary string)
    request.setContentType(multipartRequestEntity.getContentType());
}
Posted in Java, Spring, Testing | Tagged , , , | 3 Comments

Writing Unit Tests for Servlets

When writing unit tests for simple servlets you’ll need to write a lot boilerplate code for mocking out all these HttpServletRequest/Response/Context/… objects every time, plus it feels like too much of a white box test really. Surely there’s a better solution out there already for such a common task?

Included in the list of choices are amongst others:

I decided to use the Spring approach since it meant not introducing any further dependencies into the project, and served my purposes.

private MyServlet servlet;
private MyService myService;

@Before
public void setUp() throws Exception {
    // Mock all objects your servlet requires
    myService = createStrictMock(MyService.class);

    // Use a ResourceLoader that loads resources relative to the 'war' directory
    // in the test - in case your servlet loads any resources from the war
    FileSystemResourceLoader warResourceLoader = new FileSystemResourceLoader() {
        @Override
        public Resource getResource(String location) {
	    return super.getResource("war/" + location);
        }
    };

    // Create mock objects for servlet context & config
    MockServletContext context = new MockServletContext(warResourceLoader);
    MockServletConfig config = new MockServletConfig(context);

    // Create servlet
    servlet = new MyServlet();
    servlet.init(config);
    servlet.setMyService(myService);
}

Now, in the test, you call your servlet’s method and assert that the response is as expected:

@Test
public void testDoGetHttpServletRequestHttpServletResponse() throws Exception {
    // Mock script
    expect(myService.someCall()).andReturn(42);
    replay(myService);

    // Create mocks for request/response
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setParameter("myparam", "myvalue");
    MockHttpServletResponse response = new MockHttpServletResponse();
    servlet.doGet(request, response);

    // Assert response properties
    assertEquals("application/vnd.ms-excel", response.getContentType());

    // Verify if the servlet response is as expected
    // In this example, Apache POI is used to generate an Excel sheet in the servlet which is checked here
    byte[] responseContent = response.getContentAsByteArray();
    HSSFWorkbook workbook = new HSSFWorkbook(
        new ByteArrayInputStream(responseContent));
    // ...

    // Verify mock script
    verify(userManager);
}
Posted in Google Web Toolkit, Java, Spring | Tagged , , , | Leave a comment