Tag Archives: java

jetty:run maven plugin file locking on windows, a better way

If you use something like jetty:run while developing webapps on windows, sooner or later you’ll run into a problem with file locking. Any editor worth using normally lets you edit jsp files, css or js files and have the changes immediately be visible, without having to start/stop the servlet container, or (heaven forbid) rebuild the .war.

Jsp files don’t seem to be affected, because they have to be recompiled, but editing js and css files, say in a resources directory, fail.
Jetty has an extensive reference on this and if you search the web you’ll find hundreds of people parroting this in one form or another.

In my opinion, it’s a terrible solution. I most certainly do _NOT_ want to have to copy a jetty webdefault.xml file into my project, and maintain any changes made in the plugin upstream. I do _NOT_ want to have to hardcode a path to a local jetty install. I DO use more than one servlet container, and have no desire to include jetty specific garbage in my main web.xml file. But all this talk of changing the value of useFileMappedBuffer can be avoided completely.

Step back a bit, the problem is caused by NIO on windows. If you’re running jetty for embedded development purposes via jetty:run, do you really give a shit about the performance difference with hundreds of threads vs traditional blocking IO? No. Not in the least. So instead of hacking and poking jetty files, just change the plugin config to not use NIO. Like so…..

<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.18</version>
    <configuration>
        <contextPath>${project.parent.artifactId}</contextPath>
        <connectors>
            <!-- work around file locking on windows -->
            <connector implementation="org.mortbay.jetty.bio.SocketConnector">
                <port>8080</port><!-- this connector defaults to 1300 for some reason -->
            </connector>
        </connectors>
    </configuration>
</plugin>

blank is numeric, but blank is not numeric?!

Someone please explain this piece of sheer lunacy in apache commons-lang’s (otherwise superb) StringUtils

From the docs

 StringUtils.isNumeric(null)   = false
 StringUtils.isNumeric("")     = true
 StringUtils.isNumeric("  ")   = false

Insanity. I can only assume this was an error in the old code, and is now preserved for backward compatibility. :(

What you want instead is NumberUtils.isNumber()

JaxWs, Spring, and referencing the wsdl in a jar, not via http

Well, this was awkward. Spring provides a quite handy factory class for creating JaxWs clients with JaxWsPortProxyFactoryBean

The config is quite simple really, you just do:

<bean id="partnerProxy" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        <property name="serviceInterface" value="is.vf.conan.ws.ConanPartnerPortType"/>
        <property name="wsdlDocumentUrl" value="http://localhost:8088/mockConanPartnerBinding?WSDL"/>
        <property name="namespaceUri" value="http://is.vf.conan/1.0/"/>
        <property name="serviceName" value="ConanPartnerService"/>
        <property name="portName" value="ConanPartnerPort"/>
</bean>

The “namespaceUri”, “serviceName” and “portName” are all boiler plate, that you have to extract from the wsdl, and shouldn’t really have to specify, but whatever, it’s boiler plate.  “serviceInterface” has to already exist.  You  have to have generated the types and interfaces before hand. But, if you’re doing wsdl first development, and you’re reading this, you already have all that. (Update 2010-07: If you don’t want to type in all that boiler plate (and who does), see: Spring JaxWS clients with less config)

Here in the office, we have a client jar, which contains the generated types and interfaces, and the wsdls themselves.  This is easy to distribute, and lets you add in support for a new service by simply dropping in a new client jar. (The jar is made with maven, using the jaxws-maven-plugin and it’s wsimport goal)

All well and good. Except. You can’t start this application unless that wsdl is up and available. You can add

        <property name="lookupServiceOnStartup" value="false"/>

Which is certainly a good start, but what if my endpoint doesn’t actually provide the wsdl at runtime? What if the ?wsdl url suffix doesn’t work here.

Well, we have two options:

  1. Have a server running all the time to provide the wsdl, and use the “endpoint” property to specify the final destination. (yuck)
  2. Have the proxy factory reference the WSDL inside that client jar.

You will see in some docs that you can do things like this:

<property name"wsdlDocumentUrl" value="classpath:blah.wsdl"/>

This works, if the wsdl can be found. If you have the wsdl in the same class structure as the rest of your code, this is probably all you need. But if your wsdl is inside a jar in the classpath, well, I tried lots of singing and dancing, but couldn’t work out how to make a url that pointed reliably to the wsdl inside the jar. :( This made me very sad.

I really don’t like having to override things, but well…. Here’s an extended spring factory bean. You now must use the endpoint property, plus the new property “localWsdlName” as well as “lookupServiceOnStartup = false” I was going to be using endpoint properties anyway, to make it nice and easy to switch out the different test environments we use, so that was not a big problem.

“localWsdlName” refers to the path inside the jar. It _should_ be able to be a “classpath:blah” reference as well, but it’s all relative to the jar that provides the service interface.

public class VodafoneJaxWsFactoryBean extends JaxWsPortProxyFactoryBean {
    private String localWsdlName;
 
    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        // This will be a looonnng file:// url, reaching into the jar 
        // holding the service interface
        URL url = getServiceInterface().getResource(localWsdlName);
        setWsdlDocumentUrl(url);
    }
 
    public void setLocalWsdlName(String localWsdlName) {
        this.localWsdlName = localWsdlName;
    }
}

And the new config you need to use this…

    <bean id="partnerProxy" class="is.vf.conan.VodafoneJaxWsFactoryBean">
        <property name="serviceInterface" value="is.vf.conan.ws.ConanPartnerPortType"/>
        <property name="endpointAddress" value="http://localhost:8088/mockConanPartnerBinding"/>
        <property name="localWsdlName" value="/conanPartner.wsdl"/>
        <property name="lookupServiceOnStartup" value="false"/>
        <property name="namespaceUri" value="http://is.vf.conan/1.0/"/>
        <property name="serviceName" value="ConanPartnerService"/>
        <property name="portName" value="ConanPartnerPort"/>
    </bean>

There you have it! If you have everything in one big blob project, you don’t need this, just specify the localWsdlName as “classpath:blah” and you’re done.