2012-06-10 2 views
3

Я использую библиотеку, которая генерирует код на основе определений IDL. Его отличная возможность использовать общие перечисления на разных языках (Java, C и C++), но эти сгенерированные перечисления, похоже, не хорошо работают с JAX-WS.JAX-WS, @XmlJavaTypeAdapter и пользовательское перечисление

В принципе, главный класс enum 'super' состоит из двух членов: порядковый номер и имя. Он похож на это (Примечание: это в библиотеке третьей стороной и не 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 выглядит примерно так (используя день в качестве примера - но на самом деле у меня есть около 50 «перечислений», которые расширяют CustomEnum, поэтому я бы хотел, чтобы решение не позволяло мне иметь несколько копий переписей, например, сгенерированный тип 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); 
    } 
} 

Обратите внимание, что я также не хочу вмешиваться/переставлять/комментировать этот класс либо с момента создания кода.

Итак, теперь я хочу использовать этот «день» в качестве @WebParam в JAX-WS @WebMethod. Вот очень простой пример того, что я хочу быть в состоянии сделать:

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 

Что я здесь отсутствует? Я попытался использовать «День» напрямую, но поскольку он не имеет конструктора по умолчанию и не получает/устанавливает дружественный, это тоже не работает. Какие-нибудь советы?

+0

мой ответ (http://stackoverflow.com/a/11090763/383861) вдоль линий, что вы ищете? Если не сообщите мне, я могу помочь дальше. Я лидер EclipseLink JAXB (MOXy), поэтому надеюсь, что смогу помочь вам найти решение, которое будет работать. –

+0

Прошу прощения, я отсутствовал со своего стола последние 2 дня. Сегодня вечером я присмотрюсь к вашему решению. Большое спасибо! – systemoutprintln

ответ

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; 
    } 

} 

TEST CLIENT

С изменениями я предложил, я запустил свой сервис в 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> 

Service Response

<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> 
1

Похоже, это происходит сбой во время выполнения из-за @XmlJavaTypeAdapter аннотации на вашем параметре WebMethod - как о подведению вашего параметра Day запроса и ваш булев отклик в типах обертки сообщений, в вашем запросе обертке, просто объявить его как @XmlRootElement, а также объявите адаптер @XmlJavaTypeAdapter(CustomEnumAdapter.class). Таким образом, ваше объявление @Webservice не содержит аннотации @XmlJavaTypeAdapter.

+0

Я как бы понимаю, что вы говорите ... Итак, XmlJavaTypeAdapter не будет работать непосредственно на WebMethod? – systemoutprintln

+0

Да, по существу :-) –

+1

Вы можете иметь '@ XmlJavaTypeAdapter' в параметре WebMethod, как указано в вопросе. –

Смежные вопросы