2012-10-02 41 views
3

我有一個外部(即不可修改的)com.external.Money類,它有一個帶有getter和setter的java.util.Currency字段。在我的CXF JAXWS Web服務,我有類似下面的請求對象:XmlAdapter沒有在CXF中使用

@XmlRootElement 
public ExampleRequest { 
    private Money money; 
    public Money getMoney() { return money; } 
    public void setMoney(Money money) { this.money = money; } 
} 

當我嘗試啓動服務,我得到以下錯誤:

Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions 
java.util.Currency does not have a no-arg default constructor. 
    this problem is related to the following location: 
     at java.util.Currency 
     at public java.util.Currency com.external.Money.getCurrency() 
     at com.external.Money 
     at public com.external.Money com.internal.ExampleRequest.getMoney() 
     at com.internal.ExampleRequest 

所以,我創建了一個MoneyAdapter,它將Money轉換成JAXB可用的東西,即TransportableMoney類,貨幣存儲爲String。理想情況下,我會創建一個CurrencyAdapter,但由於貨幣字段被外部類封裝,所以我無法將其掛鉤(或者我不知道如何)。

我試圖掛鉤的適配器與package-info.java

@XmlJavaTypeAdapters({ 
    @XmlJavaTypeAdapter(value=MoneyAdapter.class, type=Money.class) 
}) 
package com.internal; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; 

import com.external.Money; 

的問題是,這是行不通的。相反,上述錯誤的,我現在得到:

Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions 
java.util.Currency does not have a no-arg default constructor. 
    this problem is related to the following location: 
     at java.util.Currency 
     at public java.util.Currency com.external.Money.getCurrency() 
     at com.external.Money 

我認爲這是發生,因爲com.external.Money有一個無參數的構造函數。當它沒有沒有參數的構造函數時,這個設置似乎工作。

我在這裏錯過了什麼嗎?有誰知道如何強制CXF使用XmlAdapter

EDIT

作爲布萊斯Doughan指出的那樣,上面並僅使用JAXB編組工作配置。它只是不適用於CXF 2.6.0。這是我的主要方法:

SomeService ss = new SomeService(); 
JaxWsServerFactoryBean jwsfb = new JaxWsServerFactoryBean(); 
jwsfb.setServiceClass(SomeService.class); 
jwsfb.setServiceBean(ss); 
jwsfb.setAddress("http://localhost:9020/hello"); 
jwsfb.create(); 

Maven依賴:

 <dependency> 
      <groupId>org.apache.cxf</groupId> 
      <artifactId>cxf-rt-frontend-jaxws</artifactId> 
      <version>2.6.0</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.cxf</groupId> 
      <artifactId>cxf-rt-transports-http</artifactId> 
      <version>2.6.0</version> 
     </dependency> 
     <dependency> 
      <groupId>org.apache.cxf</groupId> 
      <artifactId>cxf-rt-transports-http-jetty</artifactId> 
      <version>2.6.0</version> 
      <scope>runtime</scope> 
     </dependency> 

SomeService:

@WebService 
@SOAPBinding(use = SOAPBinding.Use.LITERAL, style = SOAPBinding.Style.DOCUMENT) 
public class SomeService { 
    public ExampleRequest getRequest() { 
     ExampleRequest request = new ExampleRequest(); 
     request.setMoney(new Money(Currency.getInstance("USD"), BigDecimal.ONE)); 
     return request; 
    } 

    public void setRequest(ExampleRequest req) { 
     // do nothing 
    } 
} 

UPDATE

創建一個JIRA ticket,看起來像它已經被解決CXF團隊(哇)!

+1

''ExampleRequest'在同一個'com.internal'包中嗎?還要確保你用'extends XmlAdapter '聲明你的適配器。還要確保你的'package-info'類正在被編譯? –

+0

嗨布萊斯,謝謝你的迴應。是 - ExampleRequest位於com.internal中,並且適配器確實擴展了XmlAdapter 。我非常確定package-info正在被編譯,因爲它對執行有影響(給出不同的錯誤信息),但是我會仔細檢查。 – andy

回答

2

下面在CXF環境以外爲我工作。你可以將它與你正在做的事情進行比較。如果你在做什麼匹配,那麼你可能遇到了CXF問題。

下面是根據您的問題的說明中的Money類的實現。

I have an external (i.e. unmodifiable) com.external.Money class that has a java.util.Currency field with getters and setters.

package com.external; 

import java.util.Currency; 

public class Money { 

    private Currency currency; 

    public Currency getCurrency() { 
     return currency; 
    } 

    public void setCurrency(Currency currency) { 
     this.currency = currency; 
    } 

} 

MoneyAdapter

下面是根據你的問題的描述MoneyAdapter實現:

So, I created a MoneyAdapter, which converts the Money into something usable by JAXB, namely a TransportableMoney class with currency stored as a String

package com.internal; 

import java.util.Currency; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 
import com.external.Money; 

public class MoneyAdapter extends XmlAdapter<TransportableMoney, Money> { 

    @Override 
    public Money unmarshal(TransportableMoney v) throws Exception { 
     Money money = new Money(); 
     Currency currency = Currency.getInstance(v.currency); 
     money.setCurrency(currency); 
     return money; 
    } 

    @Override 
    public TransportableMoney marshal(Money v) throws Exception { 
     TransportableMoney transportableMoney = new TransportableMoney(); 
     transportableMoney.currency = v.getCurrency().getCurrencyCode(); 
     return transportableMoney; 
    } 

} 

TransportableMoney

package com.internal; 

public class TransportableMoney { 

    public String currency; 

} 

包信息

這是直接從你的問題你採取類package-info

@XmlJavaTypeAdapters({ 
    @XmlJavaTypeAdapter(value=MoneyAdapter.class, type=Money.class) 
}) 
package com.internal; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; 

import com.external.Money; 

ExampleRequest

這是從你的問題直接被你ExampleRequest類。

package com.internal; 

import javax.xml.bind.annotation.XmlRootElement; 

import com.external.Money; 

@XmlRootElement 
public class ExampleRequest { 
    private Money money; 
    public Money getMoney() { return money; } 
    public void setMoney(Money money) { this.money = money; } 
} 

演示

下面是一些示例代碼,在讀取XML對象和寫回了,證明一切正常。

package com.internal; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(ExampleRequest.class); 

     File xml = new File("src/com/internal/input.xml"); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     ExampleRequest er = (ExampleRequest) unmarshaller.unmarshal(xml); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(er, System.out); 
    } 

} 

input.xml中/輸出

下面是示例輸入和輸出XML。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<exampleRequest> 
    <money> 
     <currency>USD</currency> 
    </money> 
</exampleRequest> 
+0

謝謝您將此確認爲CXF問題。如果您知道CXF中可能會發生這種情況,請告訴我。否則,我會在CXF問題跟蹤器上提出這個問題。 – andy

+0

@andy - 可能與包級別註釋有關。如果將'@ XmlJavaTypeAdapter'註釋移動到'ExampleRequest'上的'money'屬性,一切正常嗎? –

+0

是的,它的工作。但是,在我的實際項目中,我有太多的引用數量的對象,作爲參數和返回值。如果可能的話,我希望有一個包級別的註釋來處理它。我剛剛打開了以下問題:https://issues.apache.org/jira/browse/CXF-4537 – andy