JBoss Iron Jacamar

Tha’ts what I call a professional Java enterprise company - you go to http://www.jboss.org/ironjacamar to see what that is and … a stacktrace:

net.sf.ehcache.constructs.blocking.LockTimeoutException: Lock timeout. Waited more than 10000ms to acquire lock for key DefaultCacheKey{uri=’/ironjacamar’, serverName=’www.jboss.org’, locale=’en’, params={}} on blocking cache default
net.sf.ehcache.constructs.blocking.BlockingCache.get(BlockingCache.java:532)
info.magnolia.module.cache.ehcache.EhCacheWrapper.get(EhCacheWrapper.java:74)
info.magnolia.module.cache.cachepolicy.Default.shouldCache(Default.java:96)
info.magnolia.module.cache.filter.CacheFilter.doFilter(CacheFilter.java:127)
info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.i18n.I18nContentSupportFilter.doFilter(I18nContentSupportFilter.java:75)
info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.module.cache.filter.GZipFilter.doFilter(GZipFilter.java:73)
info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
info.magnolia.cms.security.BaseSecurityFilter.doFilter(BaseSecurityFilter.java:64)
info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.security.LogoutFilter.doFilter(LogoutFilter.java:88)
info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.security.auth.login.LoginFilter.doFilter(LoginFilter.java:77)
info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
info.magnolia.cms.filters.CosMultipartRequestFilter.doFilter(CosMultipartRequestFilter.java:86)
info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:60)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.filters.ContentTypeFilter.doFilter(ContentTypeFilter.java:102)
info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.filters.ContextFilter.doFilter(ContextFilter.java:120)
info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:66)
info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:88)
info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:105)
info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:216)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

Integrating Metro with Tapestry

First, we create a class Webservice for contribution web services to a RequestFilter:

package org.apache.tapestry.webservice;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.xml.ws.handler.Handler;

public class Webservice
{
    private final Class webserviceClass;

    private final Object service;

    private final String name;

    private final String urlPattern;

    @SuppressWarnings("rawtypes")
    private final List handlerChain;

    @SuppressWarnings("rawtypes")
    public Webservice(Class webserviceClass, Object service, String name, String urlPattern, Handler... handlerChain)
    {
        super();
        this.webserviceClass = webserviceClass;
        this.service = service;
        this.name = name;
        this.urlPattern = urlPattern;

        if(handlerChain == null)
            this.handlerChain = Collections.emptyList();
        else
            this.handlerChain = Arrays.asList(handlerChain);
    }

    public Class getWebserviceClass()
    {
        return webserviceClass;
    }

    public Object getService()
    {
        return service;
    }

    public String getName()
    {
        return name;
    }

    public String getUrlPattern()
    {
        return urlPattern;
    }

    @SuppressWarnings("rawtypes")
    public List getHandlerChain()
    {
        return handlerChain;
    }
}
Next, we create a HttpServletRequestFilter for handling web service requests and forwarding them tho Metro / JAX-WS:
package org.apache.tapestry.webservice;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.handler.Handler;

import org.apache.tapestry5.services.ApplicationGlobals;
import org.apache.tapestry5.services.HttpServletRequestFilter;
import org.apache.tapestry5.services.HttpServletRequestHandler;

import com.sun.xml.ws.api.BindingID;
import com.sun.xml.ws.api.WSBinding;
import com.sun.xml.ws.api.server.Container;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.binding.BindingImpl;
import com.sun.xml.ws.server.EndpointFactory;
import com.sun.xml.ws.transport.http.DeploymentDescriptorParser.AdapterFactory;
import com.sun.xml.ws.transport.http.servlet.ServletAdapter;
import com.sun.xml.ws.transport.http.servlet.ServletAdapterList;
import com.sun.xml.ws.transport.http.servlet.WSServletDelegate;

public class JaxWsHttpServletRequestFilter implements HttpServletRequestFilter
{
    private final ServletContext servletContext;

    private final WSServletDelegate wsServletDelegate;

    private final List urlPatterns;

    public JaxWsHttpServletRequestFilter(final List webservices,
        final ApplicationGlobals applicationGlobals) throws MalformedURLException
    {
        this.servletContext = applicationGlobals.getServletContext();

        Container servletContainer = new ServletContainer(servletContext);
        AdapterFactory adapterFactory = new ServletAdapterList();
        urlPatterns = new ArrayList();

        List adapters = new ArrayList();
        for (Webservice webservice : webservices)
        {
            WSBinding binding = BindingImpl.create(BindingID.parse(webservice.getWebserviceClass()));
            @SuppressWarnings("rawtypes")
            List handlerChain = binding.getHandlerChain();
            handlerChain.addAll(webservice.getHandlerChain());
            binding.setHandlerChain(handlerChain);

            @SuppressWarnings("rawtypes")
            WSEndpoint endpoint = EndpointFactory.createEndpoint(
                webservice.getWebserviceClass(),
                false,
                new ServiceInvoker(webservice.getService()),
                null,
                null,
                servletContainer,
                binding,
                null,
                null,
                null,
                true);
            adapters.add(adapterFactory.createAdapter(webservice.getName(), webservice.getUrlPattern(), endpoint));
            urlPatterns.add(webservice.getUrlPattern());
        }
        wsServletDelegate = new WSServletDelegate(adapters, servletContext);
    }

    public boolean service(HttpServletRequest request, HttpServletResponse response, HttpServletRequestHandler handler)
        throws IOException
    {
        String path = request.getServletPath();
        String pathInfo = request.getPathInfo();

        if (pathInfo != null)
            path += pathInfo;

        for (String urlPattern : urlPatterns)
        {
            if (path.startsWith(urlPattern))
            {
                try
                {
                    wsServletDelegate.doPost(request, response, servletContext);
                    return true;
                }
                catch (ServletException e)
                {
                    return false;
                }
            }
        }

        // Not a match, so let it go.

        return handler.service(request, response);
    }
}
In the WebServiceModule we add the JaxWsHttpServletRequestFilter:
public final class WebserviceModule
{
    public static void contributeHttpServletRequestHandler(
        OrderedConfiguration configuration,
        @InjectService("JaxWsHttpServletRequestFilter") HttpServletRequestFilter jaxWsHttpServletRequestFilter)
    {
        configuration.addInstance("jaxws", JaxWsHttpServletRequestFilter.class, "after:*");
    }
}
Now you can add your web service contribution to your module:
public static void contributeJaxWsHttpServletRequestFilter(final OrderedConfiguration configuration, final MyWebservice myWebservice)
{
    configuration.add("MyWebservice", new Webservice(MyWebservice.class, myWebservice,
        "MyWebservice", "/ws/MyWebservice", new SOAPLoggingHandler(
            GWS_IMPORT_ORDER_LOGGER_NAME)));
}

Restoring deleted trunk or branch in Subversion

If you ever accidentally delete a branch (or even the trunk) or any other directory in Subversion don’t panic it can be restored.

The Subversion book mentions a technique with checking out the current version and reverse merging the change in “Undoing Changes”. But this is very slow for really big repositories and it’s a bit complicated - I thought there should be an easier way and in fact, there is.

svn copy  {repoUrl}/trunk@{repoVersionBeforeDelete} {repoUrl}/trunk

E.g. if you deleted trunk in your repo http://myhost/svn in commit 1234 (so the last version with existing trunk was 1233) you restore your trunk with:

svn copy http://myhost/svn@1233 http://myhost/svn

Voila - that’s it: your trunk is ready for new commits.

Back from CONFESS 2011

Back form CONFESS 2011 - a new Austrian Java enterprise conference.

Especially liked the Gradle and JSF vs. Tapestry talks.

Seems that Groovy is on it’s way to mainstream - nearly all talks used or mentioned it apart from JSF but EE’s always some steps behind :)