Category Archives: java

View only preferences for Android

Have you ever wanted to show a bunch of statistics, or read only config or something like that, and wished you could just use the built in PreferencesActivity like you can for user editable preferences?

Just like how the stock android does for the “About Phone” page and the “SD card & phone storage” Android "preferences" that are uneditable

I wanted to have some figures like this in my own app, and I wanted them to show up under menu → preferences as well. Here’s how…

First, just declare a plain “Preference” in the layout, not an EditTextPreference or anything fancy, we’re going to make a pretty simple custom preference.

<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android" a:key="PintyPrefs">
    <PreferenceCategory>
<!-- other stuff -->
    </PreferenceCategory>
    <PreferenceCategory a:title="stats">
        <Preference a:title="@string/preference_last_data_update"              
                            a:key="preference_lookup_key"
                            a:editable="false"
                            a:defaultValue="unknown"
                />
    </PreferenceCategory>
</PreferenceScreen>

Now, in your preferences activity, just stick in some code like this…

//.. onCreate/onResume..
        lastUpdatedPref = findPreference(preference_lookup_key);
        String lastUpdated = calculateYourStatisticsSomehow();
        lastUpdatedPref.setSummary(lastUpdated);

That’s it. You can see here how I’ve got it in my own preferences dialog

In my case I wanted to see when the supporting server for my app had last been updated.

oracle destroying sun

Oh oracle, how I dislike thee. You took a perfectly good url like: “http://forums.sun.com/thread.jspa?threadID=5147616” clearly referencing a single thread, and you THREW IT AWAY giving me
http://forums.oracle.com/forums/main.jspa;jsessionid= 8d92079030d6c653c4adf7d34c40af87cbfdff6c4e77.e38Qb3qMa3eRbO0LaNqQaNaQax0Qe0?categoryID=84

And that just drops me at the root of _ALL_ the oracle forums.

“Welcome to our online community. Please choose from one of the forums below or login to start using this service”

Good job. Good fucking job.

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>

common object models in webmethods and java webservices

What all the ranting and soap tedium of the previous post was leading to, was that we want to have some common object models shared across multiple java/.Net webservices, as well as webmethods business processes.

So, we made a few nice schemas, all in one namespace, and made a few test webservices and clients, and made sure that the objects could be happily passed from one to the other without needing to do any field by field level copying.

To repeat, the object model of customers and products, is multiple schema files, all in one namespace. This makes it easier to work on one part at a time, and means less people have to get their heads around 20 different namespaces.

Each service then has it’s own separate namespace, to allow later deployment of different versions side by side, but uses the same common object model.

Because this leads to having wsdl documents that reference multiple schemas, that may reference further schemas, you need to be very fucking sure that your webservices library is doing the right thing&tm; so that everyone actually gets the types they were expecting.

JAX-WS Commons doesn’t do a very good job of this. You can _make_ it do the right thing, but it takes a lot of work. And when you want to generate code from the wsdls, and include niceties like toString and equals and hashcode and the other tasty xjc plugins, you get a world of hurt with overlapping maven plugins and snapshot dependencies. Again, you can make it work, but it’s more difficult than it should be.

CXF seems to just work so far.

And that means that webmethods can actually import wsdls from CXF, and we can be confident that those are the same ones that we wrote, and that the objects will be portable.

WebMethods gives us a nice big warningwebmethods warning about duplicate types but it works. As best I can tell, as long as your “duplicate” types really are the same, you can safely ignore this warning.

Multiple schemas in WSDL, jaxws, cxf, soapui and webmethods.

This is the _short_ version.

We write a few wsdls here. We’ve been exposing them with plain stock JAXWS built into java 6, along with JAX-WS Commons and regular spring. This has mostly been working fine. We even have some maven archetypes to generate the templates around this and it’s all well and good.

As long as your schemas and types are all in a single .wsdl file

You see, jax-ws commons is basically unmaintained. As you can see in the quickstart, you should just need this…

<wss:binding url="/sub">
    <wss:service>
      <ws:service bean="#myService" />
    </wss:service>
  </wss:binding>
 
  <!-- this bean implements web service methods -->
  <bean id="myService" class="foo.MyService" >
      <property name="something" value="somevalue"/>
  </bean>

And, that actually works. Except…. Even if you started from a wsdl, and then created a service that implemented the wsdl, the wsdl jax-ws commons will expose at runtime is generated dynamically. So none of that documentation and and xml annotations you slaved over for hours/days/weeks are actually visible anywhere.

Ok, No big deal! It’s still all standards based, we just lost our documentation. Welllll. Only if you added more annotations specifying the namespaces. If you just have the @WebService(serviceInterface = “the.generated.from.wsdl.Interface”) jax-ws commons will make you a webservice whose runtime wsdl will have a namespace created from your implementation package name! (Instead of the originally defined wsdl namespace)

So you can add more annotations, oh, one of them is wsdl location! sweet! oh. no. It can’t reference into a jar.

So you look at the wss: namespace based config, oh look, we can specify the wsdl there too! Oh. no. It can’t reference into a jar. Hmm, the schema’s broken. primaryWsdl is an attribute, but can’t be used as such…

You check the documentation again, and give it a go… Ok, primaryWsdl is a child element? Ok! this seems to work!

Then you look at your runtime wsdl…

<xsd:import schemaLocation="Core_v1.xsd" namespace="http://core.vf.is/dom/v1"/>

Hmm, how’s it going to see that file at runtime? Oops. you’ve just made an invalid wsdl. Back to the docs….. what docs? There are none. but suffice to say, there’s a magic key that does what you want… ws:metadata It’s defined as taking a list of schemas. When you get this right, it knows how to magically create runtime links to them. Of course, there’s a bug for this, but no-one’s working on it.

Except, as we mentioned, jax-ws commons is effectively unmaintained. There’s a bug in the schema that only allows one metadata element, instead of a list. So you can go and use the full expanded plain old spring config. But good lord that’s ugly. And how on earth would you have survived this far?

    <wss:binding id="wscustomer" url="/services/customer1">
        <wss:service>
            <bean class="org.jvnet.jax_ws_commons.spring.SpringService">
                <property name="bean" ref="servicesCustomer1"/>
                <property name="impl" value="is.vf.test.ws.customers.v1.CustomersV1Impl"/>
                <property name="primaryWsdl" value="customers_v1.wsdl"/>
                <property name="serviceName">
                    <bean class="javax.xml.namespace.QName">
                        <constructor-arg index="0" value="http://core.vf.is/customers/jaxws/"/>
                        <constructor-arg index="1" value="customers_v1"/>
                        <constructor-arg index="2" value="tns"/>
                    </bean>
                </property>
                <property name="portName">
                    <bean class="javax.xml.namespace.QName">
                        <constructor-arg index="0" value="http://core.vf.is/customers/jaxws/"/>
                        <constructor-arg index="1" value="customers_v1SOAP"/>
                        <constructor-arg index="2" value="tns"/>
                    </bean>
                </property>
                <property name="metadata">
                    <list>
                        <value>Core_v1.xsd</value>
                        <value>Customers_v1.xsd</value>
                        <value>ProductCatalog_v1.xsd</value>
                    </list>
                </property>
            </bean>
        </wss:service>
    </wss:binding>

There’s patches that aren’t applied, bugs not fixed, it’s a zoo. But yeah, you can make it work with the very manual and repetitive raw spring bean config.

But where did webmethods come into this?

Well, basically, it just fails abominably when it gets one of these wsdls that references unreachable schemas. And if you were using the autogenerated ones, and weren’t super careful, you ended up with types in webmethods that weren’t actually the same type.

Did I mention that when you import a wsdl into webmethods, it creates a doc type for every type, even if the same type has already been imported via another wsdl? It gives you a warning for each duplicate type, but fortunately, at run time, it seems acknowledge that the two types are actually the same thing. Thank god.

Enough of this shit.

Want to do the same thing with CXF?

     <jaxws:endpoint id="wsCustomer" implementor="#servicesCustomer1" wsdlLocation="customers_v1.wsdl" address="/customer1"
                    xmlns:kz="http://core.vf.is/customers/cxf/" serviceName="kz:customers_v1"
                    endpointName="kz:customers_v1SOAP"/>

You still have to put in the serviceName and enpointName, even though they just copied from the wsdl itself but hey, it works, it’s way more intuitive, and it’s less typing.

(Don’t even get me started on the quality of the generated types from CXF vs JAXWS-Commons.)

bleh.

eclipse 3.6 and maven archetypes with IAM/q4e

Ok, IAM for maven integrations fails the big one. It still uses the v1 archetype plugin in maven, so it completely and utterly fails to generate archetypes that are remotely recent.

Secondly, it only uses an internal list of archetypes, even if there’s more installed in your local ~/.m2 repository, and there’s no way of browsing on a remote repository, you have to type in all of it. (Intellij 9 also does this, but at least it can then do the generation steps!)

So, how about running archetype:generate from the command line, and then importing it into eclipse?

well, that kinda works. I made a new empty project, and chose to import a maven project. I pointed it at the base dir of my generated project, and it detected the two child modules, and with “experimental parents” enabled, it generated me 3 projects. Apparently that’s how eclipse works. kinda lame. My parent project has all the source of the inner projects.

This was using eclipse 3.6.1, and Eclipse IAM version 0.11.0.201001181900

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()

org.apache.xerces.parsers.XML11Configuration cannot be cast to org.apache.xerces.xni.parser.XMLParserConfiguration

Update 2010-09-29:
So, depsite being able to trigger it live, and knowing that it’s always a problem with an exception being thrown by the web service, and something in the soap fault parsing being broken, I still haven’t been able to actually fix this. Sometimes I get a parser cast error for a soapfault, sometimes I don’t. Classloader hell somewhere I presume. This one still bites me a lot, and I don’t feel any closer to permanently solving it than I did on day 1, if anything I feel further from resolution, because of how much I’ve tried.

Original post below….

Not much information out there about this one.   What little there is will indicate some sort of class path or library conflict.  That may be true, but there’s other ways of getting here.  I finally managed to trigger it myself today, and now I know what causes it.  And I’m disgusted.

DISGUSTED

Now, admittedly, I’m having a hard time coming up with a test case for this, but it very much appears that this is happening when certain characters that are illegal in XML are returned via a webservice call.  FYI, I’m using JAX-WS wsdl first services, with JAX-WS service clients.  The _clients_ throw the error.

After eventually finding one of the problem calls, I found that the invoke was actually failing on the service side, and because ERICSSON ARE MORONS, the error message included ^c in the output. While this got sent back to the client without the service failing, the client exploded, with the delightfully helpful xml parser casting error.

So, JAX-WS RI, despite being billed as non-intrusive, and something that let’s you expose your existing services as webservices, is HIGHLY INTRUSIVE, and requires that _you_ take pains to make sure you _NEVER_ send out any invalid xml.  Even in you string fields, where you should be able to use what you want.  Because, you know, the library’s just exposing my service.

Still, there’s a fine tradition of this moronic behaviour.  XFire does the same thing.  [1] They flat out refused to accept that this was something the webservices library should be handling.

[1] You’ll get something like: com.ctc.wstx.exc.WstxUnexpectedCharException: Illegal character ((CTRL-CHAR, code 3)) at line blah…

Spring JAX-WS clients, with less config

More with less. I got rather annoyed at some of the default messages that came out of the JaxWsPortProxyFactoryBean. Things like, “service name blah does not exist in the wsdl, did you mean wop?” Well, SURE! I told you the wsdl, there’s only one service, I mean THAT ONE!

So, I made my own port proxy factory….

Ugly old way

portname, serviceName and namespaceUri are all completely mechanical drudgery, but you have to get them exactly right.

    <bean id="oldStyleClient" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        <property name="serviceInterface" value="full.class.path.IService"/>
        <property name="wsdlDocumentUrl" value="http://server:port/webapp/services/BlahService?wsdl"/>
        <property name="endpointAddress" value="http://server:port/webapp/services/BlahService"/>
        <property name="lookupServiceOnStartup" value="false"/>
        <property name="portName" value="BlahServiceSOAP"/>
        <property name="serviceName" value="BlahService"/>
        <property name="namespaceUri" value="http://some.namespace/from/the/wsdl/"/>
    </bean>

Sexy new way

Sexy ways are always better ways.

    <bean id="potsClient" class="is.vf.common.jaxws.SimpleJaxWsFactory">
        <property name="serviceInterface" value="full.class.path.IService"/>
        <property name="localWsdlName" value="/BlahService.wsdl"/>
        <property name="endpointAddress" value="http://server:port/webapp/services/BlahService"/>
    </bean>

Hooray! So how? Just xpath into the wsdl! I used dom4j, because I’ve already got that in my app, but you could use anything really. I briefly tried using the xml apis in the jdk, but gave up very quickly.

Full Source below

package blah;
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean;
import java.net.URL;
 
/**
 * Set up a jaxws client with less effort.
 * Originally, I couldn't work out how to get spring/jaxws to reference a local wsdl file that was actually inside a jar.
 * And then, because I was damn sick of having to go and look up hardcoded strings from the wsdl just to copy into the config,
 * I decided to just read the damn wsdl and suck up the necessary blobs myself.
 *
 * No guarantees that this will work on all wsdls, but most people use the wsdl: prefix right?
 * Now, the only _required_ parameters are, localWsdlName and serviceInterface! whee. 
 * @author karlp
 *         Date: 8.2.2010
 */
public class SimpleJaxWsFactory extends JaxWsPortProxyFactoryBean {
    private String localWsdlName;
 
    /**
     * use dom4j to determine what's in the wsdl.
     * (I tried using the java built in methods, but a) it's ugly, and b) it didn't work)
     * Then just go back to the parent to load up the rest of the properties, now that we've done  the tedious ones...
     */
    @Override
    public void afterPropertiesSet() {
        if (localWsdlName != null) {
            URL url = getServiceInterface().getResource(localWsdlName);
            setWsdlDocumentUrl(url);
            Document doc;
            try {
                doc = new SAXReader().read(url);
            } catch (DocumentException e) {
                throw new IllegalStateException("Shouldn't be getting exceptions reading your local wsdl!" + e.getMessage(), e);
            }
            this.setServiceName(doc.selectSingleNode("//wsdl:service/@name").getStringValue());
            this.setPortName(doc.selectSingleNode("//wsdl:service/wsdl:port/@name").getStringValue());
            this.setNamespaceUri(doc.selectSingleNode("/wsdl:definitions/@targetNamespace").getStringValue());
        }
        super.afterPropertiesSet();
    }
 
    /**
     * This is the name of the wsdl, as seen in the jar containing the {@link serviceInterface}
     * @param localWsdlName the path to the wsdl in the containing jar
     */
    public void setLocalWsdlName(String localWsdlName) {
        this.localWsdlName = localWsdlName;
    }
}

xfire, inheritance and annotations, via spring

Yuck, xfire sure was about 1000% better than axis, but compared to modern jax-ws and contract first, it really can be just painful sometimes. So, I had some subclasses I wanted to expose over web services, but the directions for inheritance in xfire, either with Aegis or JaxB, both rely on you having horribly verbose spring configs.

We just use @WebService annotations, but we still needed a way to list these extra types that should be listed in the generated wsdl. (It’s worth noting that you get no errors if you don’t do this, but only fields from the parent class will be sent to web service clients)

The “fix” was committed in XFIRE-594 But as usual, the documentation got shotgunned all over somewhere. What you need for inherited types, when you’re using annotations is:

@WebService(endpointInterface = "acme.package.ISomeInterface")
@ServiceProperties(properties = {
    @ServiceProperty(key="writeXsiType", value="true"),
    @ServiceProperty(key="overrideTypesList", list = {
        "acme.package.SomeChildType",
        "acme.package.SomeOtherChildType"}) 
})
public class SomeService implements ISomeInterface
{
    // blah
    SomeParentType someMethod();
}

Then, if you’re just using the simple config from Spring remoting You’re done!