У меня есть служба SOAP, к которой нужно отправлять запросы (в частности, Веб-служба интеграции Ivanti ).
Я использую Apache CXF 3.2.7 для подключения к службе.Я генерирую Java-классы из WSDL службы, используя wsdl2java
.
. WSDL не упоминает никаких GUID и кажется полностью самодостаточным.Однако есть одно поле (с именем Value
), которое не является типизированным, т.е.е.xsd:element
без атрибута type
, и сервер отправляет ответы со значениями различных типов в этом поле.Они выглядят так:
Строки и шорты в порядке,но GUID выдают это исключение на клиенте:
javax.xml.bind.UnmarshalException: unrecognized type name: {http://microsoft.com/wsdl/types/}guid
Как мне избежать этого исключения? На самом деле меня не волнует значение этого поля, хотя решение, которое достигаетБезошибочное типизированное шифрование, конечно, было бы идеально.
То, что я пробовал
Независимо от того, что я делаю, исключение просто не исчезает.В частности, я попытался:
добавить <jaxb:binding><jaxb:property><jaxb:baseType>
в мой настраиваемый XML-код привязки, чтобы он обрабатывал поле как строку - это делало свойство Java строкой, но, по-видимому, не нарушало маршалингданные в соответствии с указанными типами и разбиты, потому что они не могут преобразовать дату в строку;
добавление <jaxb:javaType>
или <jxc:javaType>
с помощью пользовательского метода демаршаллинга - это неработать вообще, wsdl2java
не удалось с «компилятором не удалось выполнить эту настройку преобразования.Он присоединен в неправильном месте или несовместим с другими привязками », независимо от того, где я разместил элемент и какой тип Java я указал;
добавление определения типа вручную из один из этих источников :
<xs:schema elementFormDefault="qualified" targetNamespace="http://microsoft.com/wsdl/types/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
в файл службы WSDL перед вызовом wsdl2java
файла - после добавления xsd:element
в дополнение к xsd:simpleType
я наконец получил wsdl2java
для генерации метода на ObjectFactory
с аннотацией @XmlElementDecl(namespace = "http://microsoft.com/wsdl/types/", name = "guid")
, но этот метод все еще не использовался, простой String
все еще использовался везде, где мой WSDL ссылался на guid
, и UnmarshalException
сохраняется;
, даже добавляя in-Interceptor
на фазе USER_STREAM
, которая съедает весь InputStream
в строку, жестоко находитвсе вещи, которые выглядят как атрибуты GUID xsi:type
/ xmlns:q2
и заменяют их на xsi:type="xsd:string"
аналогично этому ответу - но я, должно быть, допустил некоторую ошибку, потому что исключение все еще не ушел;Вот мой код:
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
public class GuidExpungeInterceptor extends AbstractPhaseInterceptor<Message> {
private static class GuidExpungedInputStream extends ByteArrayInputStream {
private final InputStream stream;
public GuidExpungedInputStream(InputStream stream) throws IOException {
super(guidExpungedByteArray(stream));
this.stream = stream;
}
private static byte[] guidExpungedByteArray(InputStream stream) throws IOException {
String content = IOUtils.toString(stream, StandardCharsets.ISO_8859_1);
content = content.replaceAll("<Value xsi:type=\"([A-Za-z_][A-Za-z0-9_.-]*):guid\" xmlns:\\1=\"http://microsoft.com/wsdl/types/\">", "<Value xsi:type=\"xsd:string\">");
return content.getBytes(StandardCharsets.ISO_8859_1);
}
@Override
public void close() throws IOException {
stream.close();
super.close();
}
}
public GuidExpungeInterceptor() {
super(Phase.USER_STREAM);
}
@Override
public void handleMessage(Message message) {
if (message == message.getExchange().getInMessage()) {
try {
InputStream stream = message.getContent(InputStream.class);
message.setContent(InputStream.class, new GuidExpungedInputStream(stream));
} catch (IOException e) {
throw new Fault(e);
}
}
}
}
class BlahController {
BlahController() {
JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
proxyFactory.setServiceClass(FRSHEATIntegrationSoap.class);
proxyFactory.setAddress(this.properties.getFrsHeatIntegrationUrl());
this.service = (FRSHEATIntegrationSoap) proxyFactory.create();
Client client = ClientProxy.getClient(service);
client.getInInterceptors().add(new GuidExpungeInterceptor());
}
}
Затем я использую this.service
для вызова строго типизированных методов работы.Возможно, перехватчик не сохраняется за пределами локальной переменной client
?
Если я правильно понимаю (в чем я совсем не уверен), это исключение означает, что JAXB не 'У меня нет демаршаллера, зарегистрированного для типа GUID, и это должно быть решено, если бы я мог каким-то образом завладеть реестром JAXB и добавить свой собственный маршаллер.Но, посмотрев на JavaDocs в CXF, я не представляю, как или даже могу ли я получить доступ к этому реестру.Некоторые методы звучат так, будто я могу получить JAXBContext
, но я не понимаю, как я мог бы добавить что-либо к уже существующему экземпляру JAXBContext
.