Ich habe die gleichen Probleme durchgemacht. Leider (oder nicht) WebServiceTemplate mit der Implementierung von SOAPMessageFactory (wie SaajSoapMessageFactory) wird alles tun, um sicherzustellen, dass Sie ein wohlgeformtes XML als Anfrage senden, indem Sie an die Transformer von Quelle zu Ergebnis gebunden werden, einschließlich "xmlns" 'bei Kindern, wenn Sie bereits in Elternteil getan haben. Sie haben ein paar elegante Optionen zu versuchen - was nicht heißt, dass sie die einfachsten sind. Sie können auf XML-Ebene arbeiten, indem Sie die Schnittstellen javax.xml.ws.Service und Dispatch verwenden, was sehr einfach ist, wenn Sie keine SSL-Authentifizierung benötigen. Schauen Sie sich diese Links aus (erste ist geschrieben in Pt-BR):
http://www.guj.com.br/t/nfe-v2-00-veja-como-consumir-o-ws/297304
https://alesaudate.wordpress.com/2010/08/09/how-to-dynamically-select-a-certificate-alias-when-invoking-web-services/
Sie können auch eine andere Nachricht Fabrik versuchen, wie DomPoxMessageFactory. Dieser Link könnte nützlich sein:
http://forum.spring.io/forum/spring-projects/web-services/128221-webservicetemplate-get-it-to-stop-adding-soap-envelope
Wenn jedoch die Struktur Ihres Projektes zu ändern, ist keine Option (was mein Fall war), ich habe eine Lösung für Sie. Ja, ein Problem zu umgehen, aber sobald das Ziel Webservice ein ungültiges XML erwartet, ich entbindet mich: D
ich gerade erstellt Abstraktionen von HttpComponentsMessageSender und HttpComponentsConnection Klassen, die zweite ist durch die erste Methode Create (URI uri) instanziiert .So kann ich meine WebServiceTemplate wie folgt erstellen:
WebServiceTemplate wst = new WebServiceTemplate(new SaajSoapMessageFactory());
wst.setMessageSender(new CustomHttpComponentsMessageSender());
Leider müssen Sie die createConnecion Methode auf die neue Abstraktion antworten nur die benutzerdefinierte Verbindung instanziieren. Wie gesagt, es ist ein Workaround!
@Override
public WebServiceConnection createConnection(URI uri) throws IOException {
HttpPost httpPost = new HttpPost(uri);
if (isAcceptGzipEncoding()) {
httpPost.addHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
HttpTransportConstants.CONTENT_ENCODING_GZIP);
}
HttpContext httpContext = createContext(uri);
return new CustomHttpComponentsConnection(getHttpClient(), httpPost, httpContext);
}
Die Nachricht wird aus dem Inneren der Methode onSendAfterWrite (WebServiceMessage Nachricht) der HttpComponentsConnection Klasse ich abstrahieren effektiv gesendet. Überraschenderweise wird der Parameter 'message' nicht innerhalb der Methode verwendet. Es ist nur für Vererbungsregeln da. Und die gute Nachricht: Es ist eine geschützte Methode. Der Nachteil ist wiederum, dass ich fast die gesamte Klasse kopieren muss, um nur diese Methode zu ändern, sobald die Felder keine öffentliche Sichtbarkeit haben und das Framework sie in der Antwortbehandlung benötigt. Also, ich werde meine ganze Klasse schreiben unten:
public class CustomHttpComponentsConnection extends HttpComponentsConnection {
private final HttpClient httpClient;
private final HttpPost httpPost;
private final HttpContext httpContext;
private HttpResponse httpResponse;
private ByteArrayOutputStream requestBuffer;
protected CustomHttpComponentsConnection(HttpClient httpClient, HttpPost httpPost, HttpContext httpContext) {
super(httpClient, httpPost, httpContext);
Assert.notNull(httpClient, "httpClient must not be null");
Assert.notNull(httpPost, "httpPost must not be null");
this.httpClient = httpClient;
this.httpPost = httpPost;
this.httpContext = httpContext;
}
public HttpResponse getHttpResponse() {
return httpResponse;
}
public HttpPost getHttpPost() {
return httpPost;
}
@Override
protected OutputStream getRequestOutputStream() throws IOException {
return requestBuffer;
}
@Override
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
requestBuffer = new ByteArrayOutputStream();
}
@Override
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
OutputStream out = getRequestOutputStream();
String str = out.toString();
str = str.replaceAll("<NFe>", "<NFe xmlns=\"http://www.portalfiscal.inf.br/nfe\">");
ByteArrayOutputStream bs = new ByteArrayOutputStream();
bs.write(str.getBytes());
getHttpPost().setEntity(new ByteArrayEntity(bs.toByteArray()));
requestBuffer = null;
if (httpContext != null) {
httpResponse = httpClient.execute(httpPost, httpContext);
}
else {
httpResponse = httpClient.execute(httpPost);
}
}
@Override
protected int getResponseCode() throws IOException {
return httpResponse.getStatusLine().getStatusCode();
}
@Override
protected String getResponseMessage() throws IOException {
return httpResponse.getStatusLine().getReasonPhrase();
}
@Override
protected long getResponseContentLength() throws IOException {
HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
return entity.getContentLength();
}
return 0;
}
@Override
protected InputStream getRawResponseInputStream() throws IOException {
HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
return entity.getContent();
}
throw new IllegalStateException("Response has no enclosing response entity, cannot create input stream");
}
@Override
public Iterator<String> getResponseHeaderNames() throws IOException {
Header[] headers = httpResponse.getAllHeaders();
String[] names = new String[headers.length];
for (int i = 0; i < headers.length; i++) {
names[i] = headers[i].getName();
}
return Arrays.asList(names).iterator();
}
@Override
public Iterator<String> getResponseHeaders(String name) throws IOException {
Header[] headers = httpResponse.getHeaders(name);
String[] values = new String[headers.length];
for (int i = 0; i < headers.length; i++) {
values[i] = headers[i].getValue();
}
return Arrays.asList(values).iterator();
}
Auch dies der einfachste Weg ist, fand ich, wenn Projektstruktur zu ändern, ist keine Option. Hoffe das hilft.
steuern Sie den Aufruf 'transformer.transform (Source, Result)', d. H. Können Sie verschiedene Source- oder Result-Objekte übergeben, wenn Sie möchten? – wero
Nein, ich habe keine Kontrolle darüber. Das Ergebnis kommt aus dem Frühjahr. –