11

I am using JAX-WS for web services.

Whenever I use a char as a method parameter, I am getting it as an unsignedShort in the xsd (Focus on weatherLetter).

Here is the declaration:

@WebMethod
public boolean setWXtatus(
        @WebParam(name = "weatherLetter") char weatherLetter,
        @WebParam(name = "weatherDigit") int weatherDigit,
        @WebParam(name = "cloudCover") int cloudCover,
        @WebParam(name = "cloudBaseInHundredsOfFeet") int cloudBaseInHundredsOfFeet,
        @WebParam(name = "pressureInHg") int pressureInHg,
        @WebParam(name = "visibilityInKm") int visibilityInKm,
        @WebParam(name = "windSpeed") int windSpeed,
        @WebParam(name = "windDirection") int windDirection,
        @WebParam(name = "lastUpdateHour") int lastUpdateHour,
        @WebParam(name = "lastUpdateMin") int lastUpdateMin
) 

Here is the type mappings I get:

<xs:complexType name="setWXStatus">
<xs:sequence>
<xs:element name="weatherLetter" type="xs:unsignedShort" minOccurs="0"/>
<xs:element name="weatherDigit" type="xs:int"/>
<xs:element name="cloudCover" type="xs:int"/>
<xs:element name="cloudBaseInHundredsOfFeet" type="xs:int"/>
<xs:element name="pressureInHg" type="xs:int"/>
<xs:element name="visibilityInKm" type="xs:int"/>
<xs:element name="windSpeed" type="xs:int"/>
<xs:element name="windDirection" type="xs:int"/>
<xs:element name="lastUpdateHour" type="xs:int"/>
<xs:element name="lastUpdateMin" type="xs:int"/>
</xs:sequence>
</xs:complexType>

How can I get weatherLetter to generate as a Char or 1 Letter String or something?

bdoughan
  • 147,609
  • 23
  • 300
  • 400
mainstringargs
  • 13,563
  • 35
  • 109
  • 174

4 Answers4

10

Update:

One way to do this is the in XSD (if you do contract first) e.g. add an XSD Restriction to it directly, e.g.

<xs:element name="singleChar">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:length value="1"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>

But I think the question is on contract last (e.g. write code that generates the XSD, not vice versa)

This is not yet supported in JAX-WS or JAXB, as far as I know (but a nice enhancement request)

Sources:

JAX-WS and JAXB don't have support for code generation for restrictions from XSD (e.g. xsd:restriction) http://old.nabble.com/Does-jaxb-2.1-enforce-xs:restriction-td21348458.html

The reason is that the other direction (generating restrictions by Annotation), is not supported too

Workaround:

Take a look at this: http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.5/tutorial/doc/JAXBUsing4.html

And also at this question:

JAX-WS and Joda-Time?

Not doing exactly what you want, but getting you a little bit closer


I don't think you can have it limited to 1 char any other way, a char is indeed an unsigned short, and the closest thing you can to limiting to 1 "String" char.

If you use a String, you will allow unlimited chars. and @WebParam doesn't have an API to limit length

Actually I didn't see a way to do XSD restrictions at all using JAX-WS, but I may be wrong

Community
  • 1
  • 1
Eran Medan
  • 44,555
  • 61
  • 184
  • 276
5

char and java.lang.Character require you to enter custom mappings since default mappings from char or java.lang.Character to WSDL XSD do not exist.

Quoted from http://publib.boulder.ibm.com/infocenter/radhelp/v6r0m1/index.jsp?topic=%2Fcom.ibm.etools.webservice.creation.doc%2Fconcepts%2Fcsoaptover.html

Hyangelo
  • 4,784
  • 4
  • 26
  • 33
5

Use an adapter, something like:

import javax.xml.bind.annotation.adapters.XmlAdapter;


public class CharAdapter extends XmlAdapter<String, Character> {

    @Override
    public String marshal(Character c) throws Exception
    {
        return String.valueOf(c);
    }

    @Override
    public Character unmarshal(String s) throws Exception
    {
    if(s == null) {
        return null;
    }
    if(s.length() != 1) {
        throw new IllegalArgumentException("Provided string \"" + s + 
                "\" has invalid length of " + s.length() + " should be 1");
    }
        return s.charAt(0);
    }

}

And then in your WXStatus (define a single class as the input argument instead of passing in loads of individual parameters - JAX is already turning this into a complexType so you may as well, plus it's a better OOP style), add this annotation (to either field or getter):

@XmlJavaTypeAdapter(CharAdapter.class)
char weatherLetter;

This will allow un/marshalling on your server-side and the client will see it as an xs:string. One side effect is as we're using primitive wrapper for char, you'll have to handle null.

UPDATE EDIT: I don't think there's any way you can specify the length of the string with this though, without manually creating/editing your WSDL with something like:

<xs:simpleType name="weatherLetter">
  <xs:annotation>
    <xs:documentation>weather character info blah blah</xs:documentation>
  </xs:annotation>
  <xs:restriction base="xs:string">
    <xs:length value="1"/>
  </xs:restriction>
</xs:simpleType>
earcam
  • 6,662
  • 4
  • 37
  • 57
  • 2
    +1 - I'm the EclipseLink JAXB (MOXy) lead, and this is exactly what I would have proposed. – bdoughan Sep 02 '11 at 17:58
  • 1
    @Blaise - Would you say that a `@XsdRestriction` annotation is a valid enhancement request then? it is lost from XSD to Bean, seems like a gap to me, how can one tell if it's in the roadmap for JAXB? – ruchirhhi Sep 02 '11 at 21:34
  • 1
    @ruchirhhi - A common request is to leverage the Bean Validation annotations (JSR-303) for restrictions. The best way to proceed is for you to add a feature request with an individual implementation (Metro: http://java.net/jira/browse/JAXB/, MOXy: https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EclipseLink). – bdoughan Sep 06 '11 at 15:42
1

You should try changing it from char to String in your declaration if you are to receive just a single character, if you're programming the client side there shouldn't be much trouble in doing so

8vius
  • 5,786
  • 14
  • 74
  • 136