4

IDL定義に基づいてコードを生成するライブラリを使用しています。さまざまな言語(Java、C、およびC ++)で一般的な列挙型を使用できるのは素晴らしいことですが、これらの生成された列挙型はJAX-WSではうまく機能しないようです。

基本的に、メイン列挙型の「super」クラスには、序数と名前の2つのメンバーがあります。これに似ています(注:これはサードパーティのライブラリにあり、JavaBeanに対応していません):

public class CustomEnum {

    int _ordinal;
    String _name;

    public CustomEnum(int ordinal, String name) {
        this._ordinal = ordinal;
        this._name = name;
    }


    public int ordinal() {
        return _ordinal;
    }

    public String name() {
        return _name;
    }
}

したがって、IDL定義に基づいて生成されたコードは次のようになります(例としてDayを使用しますが、実際にはCustomEnumを拡張する約50の「列挙型」があるので、複数の列挙型が発生しないようにするソリューションが必要ですIDLで生成されたタイプやjava.lang.enumなどの列挙型のコピー):

public class Day extends CustomEnum {

    public static final Day Sunday = new Day(0, "Sunday");
    public static final Day Monday = new Day(1, "Monday");
    public static final Day Tuesday = new Day(2, "Tuesday");
    public static final Day Wednesday = new Day(3, "Wednesday");
    public static final Day Thursday = new Day(4, "Thursday");
    public static final Day Friday = new Day(5, "Friday");
    public static final Day Saturday = new Day(6, "Saturday");

    public Day(int ordinal, String name) {
        super(ordinal, name);
    }
}

また、生成されたコードであるため、このクラスをいじったり、再配置したり、注釈を付けたりしたくないことに注意してください。

したがって、今私がやりたいのは、この「Day」列挙型をJAX-WS@WebMethodの@WebParamとして使用できるようにすることです。これが私がやりたいことの非常に簡単な例です:

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

    @WebService
    public class EnumEndpoint {

        @WebMethod
        public boolean callEndpoint(
                @XmlJavaTypeAdapter(CustomEnumAdapter.class) Day day) {
            System.out.println(day.ordinal() + " " + day.name());
            return false;
        }

    }

私は次のようにXmlJavaTypeAdapterを書くことで期待していました:

import java.lang.reflect.Type;

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

public class CustomEnumAdapter extends XmlAdapter<CustomEnum, EnumBean>
        implements Type {

    @Override
    public EnumBean unmarshal(CustomEnum v) throws Exception {
        EnumBean mine = new EnumBean(v.ordinal(), v.name());
        return mine;
    }

    @Override
    public CustomEnum marshal(EnumBean v) throws Exception {
        CustomEnum customEnum = new CustomEnum(v.getOrdinal(),v.getName());
        return customEnum;
    }

}

EnumBeanは次のようになります。

public class EnumBean {

    int ordinal;
    String name;

    public EnumBean(int ordinal, String name) {
        this.ordinal = ordinal;
        this.name = name;
    }

    public int getOrdinal() {
        return ordinal;
    }

    public void setOrdinal(int ordinal) {
        this.ordinal = ordinal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

しかし、次のようにサーバーエンドポイントを宣言すると、次のようになります。

import javax.xml.ws.Endpoint;

public class Server {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Endpoint.publish("http://0.0.0.0:7979/enum", new EnumEndpoint());

    }

}

このエラーが発生します:

Jun 10, 2012 3:29:21 PM com.sun.xml.internal.ws.model.RuntimeModeler getRequestWrapperClass
INFO: Dynamically creating request wrapper Class test.jaxws.CallEndpoint
Exception in thread "main" javax.xml.ws.WebServiceException: java.lang.IllegalArgumentException: value class test.CustomEnumAdapter
    at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createRequestWrapperBean(WrapperBeanGenerator.java:249)
    at com.sun.xml.internal.ws.model.RuntimeModeler.getRequestWrapperClass(RuntimeModeler.java:280)
    at com.sun.xml.internal.ws.model.RuntimeModeler.processDocWrappedMethod(RuntimeModeler.java:674)
    at com.sun.xml.internal.ws.model.RuntimeModeler.processMethod(RuntimeModeler.java:612)
    at com.sun.xml.internal.ws.model.RuntimeModeler.processClass(RuntimeModeler.java:401)
    at com.sun.xml.internal.ws.model.RuntimeModeler.buildRuntimeModel(RuntimeModeler.java:240)
    at com.sun.xml.internal.ws.server.EndpointFactory.createSEIModel(EndpointFactory.java:312)
    at com.sun.xml.internal.ws.server.EndpointFactory.createEndpoint(EndpointFactory.java:178)
    at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:456)
    at com.sun.xml.internal.ws.api.server.WSEndpoint.create(WSEndpoint.java:475)
    at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(EndpointImpl.java:213)
    at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:143)
    at com.sun.xml.internal.ws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:102)
    at javax.xml.ws.Endpoint.publish(Endpoint.java:170)
    at test.Server.main(Server.java:11)
Caused by: java.lang.IllegalArgumentException: value class test.CustomEnumAdapter
    at com.sun.xml.internal.ws.org.objectweb.asm.ClassWriter.newConstItem(ClassWriter.java:893)
    at com.sun.xml.internal.ws.org.objectweb.asm.AnnotationWriter.visit(AnnotationWriter.java:185)
    at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createBeanImage(WrapperBeanGenerator.java:111)
    at com.sun.xml.internal.ws.model.WrapperBeanGenerator.createRequestWrapperBean(WrapperBeanGenerator.java:245)
    ... 14 more

ここで何が欠けていますか?'Day'を直接使用しようとしましたが、デフォルトのコンストラクターがなく、get / setに対応していないため、これも機能しません。任意のヒント?

4

2 に答える 2

4

EnumBean

EnumBeanが適応されたクラスである場合、デフォルトのコンストラクターが必要です。

package forum10972195;

public class EnumBean {

    int ordinal;
    String name;

    public EnumBean() {

    }

    public EnumBean(int ordinal, String name) {
        this.ordinal = ordinal;
        this.name = name;
    }

    public int getOrdinal() {
        return ordinal;
    }

    public void setOrdinal(int ordinal) {
        this.ordinal = ordinal;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

CustomEnumAdapter

また、適応されたクラスは、拡張時に最初のパラメーターとして表示される必要がありますXmlAdapter。マッピング先のパラメーターはタイプであるため、バインドされたタイプとして指定するDay必要があります。XmlAdapterDay

package forum10972195;

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

public class CustomEnumAdapter extends XmlAdapter<EnumBean, Day> {

    @Override
    public EnumBean marshal(Day v) throws Exception {
        EnumBean mine = new EnumBean(v.ordinal(), v.name());
        return mine;
    }

    @Override
    public Day unmarshal(EnumBean v) throws Exception {
        Day day = new Day(v.getOrdinal(),v.getName());
        return day;
    }

}

テストクライアント

私が提案した変更を加えて、WebLogic 12.1.1 でサービスを実行し、組み込みのテスト クライアントを使用して、次の結果を得ました。

サービス要求

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
  <env:Header />
    <env:Body>
    <callEndpoint xmlns="http://forum10972195/">
      <!--Optional:-->
      <arg0 xmlns="">
        <!--Optional:-->
        <name>string</name>
        <ordinal>3</ordinal>
      </arg0>
    </callEndpoint>
  </env:Body>
</env:Envelope>

サービスレスポンス

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
    <ns0:callEndpointResponse xmlns:ns0="http://forum10972195/">
      <return>false</return>
    </ns0:callEndpointResponse>
  </S:Body>
</S:Envelope>
于 2012-06-18T20:46:35.033 に答える
1

webmethod パラメーターの @XmlJavaTypeAdapter アノテーションが原因で、実行時に失敗しているように聞こえます。リクエスト パラメーターDayとブール値の応答をラッパー メッセージ タイプでラップし、リクエスト ラッパーで as として@XmlRootElement宣言し、 adapter を宣言するだけ@XmlJavaTypeAdapter(CustomEnumAdapter.class)です。このように、 @Webservice 宣言には @XmlJavaTypeAdapter アノテーションがありません。

于 2012-06-11T00:52:28.840 に答える