when I send invalid xml to my web services on websphere server, I get java heap space:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Header/>
<soap:Body>
<MyElementsomething</MyElement>
</soap:Body>
</soap:Envelope>
with the element
<MyElement>something</MyElement>
Everything works ok
Exception:
java.lang.OutOfMemoryError: Java heap space
at com.ibm.ws.webservices.utils.BAIS.create(BAIS.java:74) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.utils.WebServicesInputSource.getBAISContent(WebServicesInputSource.java:744) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.utils.WebServicesInputSource.getByteArrayContent(WebServicesInputSource.java:710) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.utils.WebServicesInputSource.getStringContent(WebServicesInputSource.java:674) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.utils.WebServicesInputSource.getString(WebServicesInputSource.java:425) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.engine.SOAPPart._getSOAPEnvelope(SOAPPart.java:1090) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.engine.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:628) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.engine.SOAPPart.getEnvelope(SOAPPart.java:656) ~[com.ibm.ws.runtime.jar:?]
at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:155) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.soap.saaj.SaajSoapMessage.getSaajVersion(SaajSoapMessage.java:257) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.soap.saaj.SaajSoapMessage.getImplementation(SaajSoapMessage.java:342) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.soap.saaj.SaajSoapMessage.<init>(SaajSoapMessage.java:117) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:186) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:60) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.transport.AbstractWebServiceConnection.receive(AbstractWebServiceConnection.java:90) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:86) ~[spring-ws-core-2.1.0.RELEASE.jar:?]
EDIT:
nobody know ?
PS: spring validation doesnt help because it is after websphere stuff. When I send invalid xml agains xsd (for example string instead of number) then it works:
2015-02-18 10:12:46.128 [WebContainer : 8] WARN cz.isvs.ais3.ws.interceptor.ServerPayloadValidatingInterceptor - XML validation error on request: cvc-datatype-valid.1.2.1: 'b' is not a valid value for 'integer'.
2015-02-18 10:12:46.128 [WebContainer : 8] WARN cz.isvs.ais3.ws.interceptor.ServerPayloadValidatingInterceptor - XML validation error on request: cvc-type.3.1.3: The value 'b' of element 'urn1:Ais' is not valid.
because of WebServiceMessageReceiverObjectSupport.class:
86 WebServiceMessage request = connection.receive(getMessageFactory()); // here occurs out of memory
87 MessageContext messageContext = new DefaultMessageContext(request, getMessageFactory());
88 receiver.receive(messageContext); // and in this method are interceptor which validate request
PS2:
when I tried to increase heap space from 2gb to 4gb there is another exception on the same spot:
java.lang.IndexOutOfBoundsException
at java.io.PushbackInputStream.read(PushbackInputStream.java:181) ~[?:1.7.0]
at java.io.FilterInputStream.read(FilterInputStream.java:133) ~[?:1.7.0]
at com.ibm.ws.webservices.utils.WebServicesInputSource$FilterIS.read(WebServicesInputSource.java:805) ~[com.ibm.ws.runtime.jar:?]
at com.ibm.ws.webservices.utils.BAIS.create(BAIS.java:77) ~[com.ibm.ws.runtime.jar:?]
PS3:
this is correct behavior with sun java:
Caused by: org.xml.sax.SAXParseException: The element type "urn:ZadostInfo" must be terminated by the matching end-tag "</urn:ZadostInfo>".
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) ~[?:?]
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source) ~[?:?]
at org.xml.sax.helpers.XMLFilterImpl.parse(Unknown Source) ~[?:?]
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(Unknown Source) ~[?:?]
at com.sun.xml.internal.messaging.saaj.util.transform.EfficientStreamingTransformer.transform(EfficientStreamingTransformer.java:411) ~[?:1.7.0]
at com.sun.xml.internal.messaging.saaj.soap.EnvelopeFactory.createEnvelope(EnvelopeFactory.java:115) ~[?:1.7.0]
at com.sun.xml.internal.messaging.saaj.soap.ver1_1.SOAPPart1_1Impl.createEnvelopeFromSource(SOAPPart1_1Impl.java:80) ~[?:1.7.0]
at com.sun.xml.internal.messaging.saaj.soap.SOAPPartImpl.getEnvelope(SOAPPartImpl.java:140) ~[?:1.7.0]
at org.springframework.ws.soap.saaj.support.SaajUtils.getSaajVersion(SaajUtils.java:155) ~[spring-ws-core-2.1.2.RELEASE.jar:?]
This looks like a Websphere bug. Using Spring-WS I got the some error:
java.lang.OutOfMemoryError: Java heap space
at com.ibm.ws.webservices.utils.BAIS.create(BAIS.java:74)
I managed to solved this way: put in /AppServer/lib/ext this library: axis2-saaj-1.6.2.jar (worked for me on Websphere v8.5 and Spring-WS v2.2.0, but you may have to change the version).
Explanation
When Spring-WS asks for a javax.xml.soap.MessageFactory implementation it gets a com.ibm.ws.webservices.engine.soap.MessageFactoryImpl instance (from Websphere runtime) instead of a com.sun.xml.internal.messaging.saaj.soap.MessageFactoryImpl instance (from JVM), which leads to the mentioned error.
The axis2-saaj library also contains a javax.xml.soap.MessageFactory implementation: org.apache.axis2.saaj.MessageFactoryImpl. This one is now used when axis2-saaj is in lib/ext folder and error is gone (I also configured PARENT LAST classpath, don't know if it matters here)
Update
#hudi your solution is correct, I just tested it. Sadly, cannot upvote you.
the best way is to use spring payloadinterceptor to validate the incoming xml against the XML schema before it allows to be parsed further...
Sample code:
bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/conf/MyElement.xsd"/>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="false"/>
For more details, read the spring documentation
You just found a bug. Please report the bug. Since this is related to the parsing. You can do two things.
First of all you can take a memory dump. Just dump the memory (or profile this using visualvm and make a memory profile run). This way you understand what polutes the memory.
Second you can correct the issue you found. I do it all the way with third party code. So just before they step into parsing the snippet you do another step evaluating if the xml is correct without checking for shema. Just use a parser run with no shema involved.
In order to provide a modified implementation use the sourcecode or if not available, decompile it or rename the class and provide a new implementation class extending from this. If it is a private method or feature you need to access just modify the byte code.
In order to inject your version just add your class to your class path (or the classpath of the websphere) and put it in front of it. Usually your code is preceeded for any library code. This way you can override every implementation detail of any library as long as you control the classpath (usually by setting it within the java.exe.
So just add an additional test for correctness before this bugged version is issued. And report the bug and also blog about it.
If you have questions or need a tool advice just ask. I do this on a regular basis. With open source and non-open source software. Also great for other things like extending features.
I tried to fix this by my own. I examined how spring-ws validate xml and tried to do it before websphere. Here is code. I test it and it is working for me.
public class SaajSoapMessageValidatorFactory extends SaajSoapMessageFactory {
#Override
public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
InputStream original;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(inputStream, baos);
original = new ByteArrayInputStream(baos.toByteArray());
InputStream validate = new ByteArrayInputStream(baos.toByteArray());
try {
ValidatorResources validator = new XmlValidatorResources(validate);
validator.process();
} catch (Exception parseException) {
throw new InvalidXmlException("Could not parse XML", parseException);
} finally {
IOUtils.closeQuietly(validate);
}
} finally {
IOUtils.closeQuietly(inputStream);
}
return super.createWebServiceMessage(original);
}
}
public class XmlValidatorResources extends ValidatorResources {
private static final long serialVersionUID = 1L;
public XmlValidatorResources(InputStream in) throws IOException, SAXException {
Digester digester = new Digester();
digester.push(this);
digester.parse(in);
}
}
and in spring context I add:
<bean id="messageFactory" class="cz.isvs.ais3.ws.validator.SaajSoapMessageValidatorFactory" />
After Martin advise I try to decompile ibm code and I think problem is in this procedure:
private SOAPEnvelope _getSOAPEnvelope()
throws WebServicesFault
{
SOAPEnvelope soapEnvelope = _getCachedSOAPEnvelope();
if(soapEnvelope == null)
if(currentForm == 4)
{
soapEnvelope = (SOAPEnvelope)getCurrentMessage();
} else
{
if(log.isDebugEnabled())
log.debug("Converting " + formNames[currentForm] + " to " + formNames[4]);
MessageContext mc = getMessage().getMessageContext();
if(mc != null)
if(mc.isHighFidelity())
{
if(originalContent == null)
originalContent = _getCachedWebServicesInputSource();
} else
{
originalContent = null;
}
WebServicesInputSource wsis = _getWebServicesInputSource();
if(log.isDebugEnabled())
log.debug("Parsing inputSource " + wsis.dumpStats());
String encoding = getMessage().getCharacterEncoding();
if(encoding != null)
wsis.setEncoding(encoding);
DeserializationContext dser = new DeserializationContextImpl(wsis, getMessage().getMessageContext(), getMessage().getMessageType(), getMessage().getSOAPConstants(), Utils._isSAAJ13Enabled());
try
{
dser.parse();
}
catch(SAXException e)
{
FFDCFilter.processException(e, "com.ibm.ws.webservices.engine.SOAPPart.getSOAPEnvelope", "964", this);
Exception real = e.getException();
wsis.reset();
if(real instanceof WebServicesFault)
throw (WebServicesFault)real;
if(originalContent == null)
originalContent = wsis;
problem section:
if(originalContent == null)// I am not sure but I think this will never happend. So to fix it I will delete this condition and throw this
exception not the second one where it want to display message
throw WebServicesFault.makeFault("To see the message containing the parsing error in the log, either enable web service engine tracing or set MessageContext.setHighFidelity(true).", ((Throwable) (real == null ? ((Throwable) (e)) : ((Throwable) (real)))));
else
throw WebServicesFault.makeFault("Message being parsed: " + originalContent.getString(), ((Throwable) (real == null ? ((Throwable) (e)) : ((Throwable) (real)))));
}
if(log.isDebugEnabled())
log.debug("Done parsing inputSource.");
originalParseLength = wsis.getContentLength();
soapEnvelope = dser.getEnvelope();
setCurrentForm(soapEnvelope, 4);
String messageProtocol = getMessage().getSOAPConstants().getSOAPProtocol();
String factoryProtocol = soapEnvelope.getSOAPFactory().getSOAPConstants().getSOAPProtocol();
String envelopeProtocol = "SOAP 1.1 Protocol";
String ns = soapEnvelope.getNamespaceURI();
if(soapEnvelope.getNamespaceURI().equals("http://schemas.xmlsoap.org/soap/envelope/"))
envelopeProtocol = "SOAP 1.2 Protocol";
if(messageProtocol.equals("Dynamic Protocol"))
{
getMessage().setSOAPConstants(soapEnvelope.getSOAPFactory().getSOAPConstants());
messageProtocol = getMessage().getSOAPConstants().getSOAPProtocol();
}
if(envelopeProtocol.equals(factoryProtocol) && factoryProtocol.equals(messageProtocol))
{
if(log.isDebugEnabled())
log.debug("The protocol is: " + envelopeProtocol);
} else
if(log.isDebugEnabled())
{
log.debug("The SOAPEnvelope protocol is: " + envelopeProtocol);
log.debug("The SOAPFactory protocol is: " + factoryProtocol);
log.debug("The SOAPMessage protocol is: " + messageProtocol);
}
}
return soapEnvelope;
}
Refer to IBM developer wroks post
https://developer.ibm.com/answers/questions/291621/how-to-resolve-outofmemoryerror-when-sending-inval.html
Customer using WebSphere 8.5.5.x with SDK 1.7 and using SAAJ with Spring frmae work may encounter OutOfMemoryError when sending SOAP request that that has invalid request. This is due to bug fix went into SDK 1.7 and later versions.
IBM has fixed this issue through IBM SDK APAR IV73614.
Details of the bug fix went in later releases
JAVA.IO.PACKEDINPUTSTREAM.AVAILABLE() RETURNS INTEGER.MAX_VALUE I.E., 2147483647 ON EMPTY STREAM IN JAVA 7
From javacore stack indicate following 4XESTACKTRACE at com/ibm/ws/webservices/utils/BAIS.create(BAIS.java:74) 4XESTACKTRACE at com/ibm/ws/webservices/utils/WebServicesInputSource.getBAISContent(WebServicesInputSource.java:744) 4XESTACKTRACE at com/ibm/ws/webservices/utils/WebServicesInputSource.getByteArrayContent(WebServicesInputSource.java:710) 4XESTACKTRACE at com/ibm/ws/webservices/utils/WebServicesInputSource.getStringContent(WebServicesInputSource.java:674) 4XESTACKTRACE at com/ibm/ws/webservices/utils/WebServicesInputSource.getString(WebServicesInputSource.java:425(Compiled Code)) 4XESTACKTRACE at com/ibm/ws/webservices/engine/SOAPPart._getSOAPEnvelope(SOAPPart.java:1090(Compiled Code)) 4XESTACKTRACE at com/ibm/ws/webservices/engine/SOAPPart.getAsSOAPEnvelope(SOAPPart.java:628(Compiled Code)) 4XESTACKTRACE at com/ibm/ws/webservices/engine/SOAPPart.getEnvelope(SOAPPart.java:656(Compiled Code)) 4XESTACKTRACE at org/springframework/ws/soap/saaj/support/SaajUtils.getSaajVersion(SaajUtils.java:155) 4XESTACKTRACE at org/springframework/ws/soap/saaj/SaajSoapMessage.getSaajVersion(SaajSoapMessage.java:257) 4XESTACKTRACE at org/springframework/ws/soap/saaj/SaajSoapMessage.getImplementation(SaajSoapMessage.java:342(Compiled Code))
Related
I am attempting to retrieve a secret from aws secrets manager. My application can retrieve 3 / 4 secrets. When attempting to retrieve the 2nd secret, i get an interrupt exception. The code below is what i am using. I am unsure where to look or why this is happening. It consistently happens when attempting to retrieve the 2nd secret. I have verified that it exists in aws and that it contains the value i expect.
I am using the reativerse [https://github.com/reactiverse/aws-sdk] library in tandem with vert.x + aws sdk 2. Any help or pointers on where to look would be greatly appreciated. The exception i see and the code i have are written below.
java.util.concurrent.ExecutionException: software.amazon.awssdk.core.exception.SdkClientException
at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:395)
at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1999)
at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$1(ContextImpl.java:157)
at io.vertx.core.impl.TaskQueue.run(TaskQueue.java:76)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: software.amazon.awssdk.core.exception.SdkClientException
at software.amazon.awssdk.core.exception.SdkClientException$BuilderImpl.build(SdkClientException.java:98)
at software.amazon.awssdk.core.internal.http.AmazonAsyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonAsyncHttpClient.java:189)
at software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler.invoke(BaseAsyncClientHandler.java:271)
at software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler.doExecute(BaseAsyncClientHandler.java:213)
at software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler.lambda$execute$1(BaseAsyncClientHandler.java:91)
at software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler.measureApiCallSuccess(BaseAsyncClientHandler.java:277)
at software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler.execute(BaseAsyncClientHandler.java:74)
at software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler.execute(AwsAsyncClientHandler.java:52)
at software.amazon.awssdk.services.secretsmanager.DefaultSecretsManagerAsyncClient.getSecretValue(DefaultSecretsManagerAsyncClient.java:1142)
... 8 more
Caused by: software.amazon.awssdk.core.exception.SdkInterruptedException
at software.amazon.awssdk.core.internal.http.InterruptMonitor.checkInterrupted(InterruptMonitor.java:40)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage.execute(ApplyTransactionIdStage.java:43)
at software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage.execute(ApplyTransactionIdStage.java:29)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
at software.amazon.awssdk.core.internal.http.AmazonAsyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonAsyncHttpClient.java:185)
... 16 more
private final SecretsManagerAsyncClient client = VertxSdkClient.withVertx(SecretsManagerAsyncClient.builder(), ctx).build();
public <T> Promise<T> getSecret(String secretName) {
Promise<T> completableFuture = Promise.promise();
Context ctx = Vertx.vertx().getOrCreateContext();
ctx.owner().executeBlocking(blockingFuture -> {
try {
GetSecretValueRequest valueRequest = GetSecretValueRequest.builder().secretId(secretName).build();
CompletableFuture<GetSecretValueResponse> valueResponse = this.client.getSecretValue(valueRequest);
GetSecretValueResponse getResponse = valueResponse.get();
String response = getResponse.secretString();
completableFuture.complete((T) Json.decodeValue(response, new <T>Object().getClass()));
blockingFuture.complete();
} catch (Exception e) {
// log exception.
}
});
...
}
See SdkInterruptedException ...it has one method getResponse():
try {
// provoke the exception in here
} catch (SdkInterruptedException e) {
System.err.println(e.getResponse());
}
This should (hopefully) at least tell why the request had been interrupted.
// log exception. is not the correct approach to handle any Exception.
The SdkClientException might be more relevant than the SdkInterruptedException:
try { ...
} catch (SdkClientException e) {
// log that exception, instead of ignoring it.
System.err.println(e.getMessage());
}
This is how an Authorization Header (AWS Signature Version 4) should basically look alike.
It may well be, that HMAC-SHA256 headers are being enforced (they're different on each single request). I could even provide a known to be working example... which would show how to configure the SecretsManagerClient. I'd suspect the root cause related to that client's configuration.
When I read "when attempting to retrieve the 2nd secret", this with high probability means that you need a refresh the HMAC-SHA256 signature before the second request will be performed. Destroying the client and constructing it again may be one sloppy workaround. When seeing duplicate values for AWS4-HMAC-SHA256 header on both requests, this definitely is the cause.
For a few days I try to resolve following issue:
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Security configuration could not be detected. Potential cause: Make sure jaxws:client element with name attribute value matching endpoint port is defined as well as a ws-security.signature.properties element within it.
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:158)
at com.sun.proxy.$Proxy38.getSignedDocument(Unknown Source)
at pl.mycompany.epuap.TPSigning_TPSigning_Client.main(TPSigning_TPSigning_Client.java:55)
Caused by: org.apache.cxf.ws.policy.PolicyException: Security configuration could not be detected. Potential cause: Make sure jaxws:client element with name attribute value matching endpoint port is defined as well as a ws-security.signature.properties element within it.
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.policyNotAsserted(AbstractBindingBuilder.java:315)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getSignatureBuilder(AbstractBindingBuilder.java:1851)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignature(AsymmetricBindingHandler.java:570)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:149)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:98)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:176)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:90)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:572)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:481)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:136)
... 2 more
This happens when I try to call webservice: https://pz.gov.pl/pz-services/tpSigning?wsdl with external (referenced) policy: https://pz.gov.pl/pz-services/tpSigning?wsdl=wssec-policies.wsdl.
Here is my code:
Properties properties = new Properties();
properties.put("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
properties.put("org.apache.ws.security.crypto.merlin.keystore.type",config.getKeystoreType());
properties.put("org.apache.ws.security.crypto.merlin.keystore.password",config.getKeystorePass());
properties.put("org.apache.ws.security.crypto.merlin.keystore.alias",config.getKeystoreAlias());
properties.put("org.apache.ws.security.crypto.merlin.file", config.getKeystoreFile());
outProps.put("cryptoProperties",properties);
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE);
//outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.USER, config.getKeystoreAlias());
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName());
outProps.put(WSHandlerConstants.SIG_PROP_REF_ID,"cryptoProperties");
outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{}{http://schemas.xmlsoap.org/soap/envelope/}Body");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
try{
String s = signing.addDocumentToSigning(doc, succesUrl, failureUrl, additionalInfo);
return s;
}
As I noticed, the policies aren't at all loaded by CXF engine. I tried to load policies by interceptors, but the effect is the same.
The probelm occurs also in 2.7.18 as in 3.x version.
Any help will be highly appreciated.
Regards
Mariusz
The problem is that you are mixing the "action" based approach to WS-Security, and the WS-SecurityPolicy driven approach. The WSDL you reference contains a security policy, and the CXF PolicyBasedWSS4JOutInterceptor will automatically take care of configuring security based on this. You just need to specify a few security configuration options, e.g. keystores. See here for more information: https://cxf.apache.org/docs/ws-securitypolicy.html
I'm doing a java web app with a servlet and I wanted to write some tests to check its functionality (ex. authorization form). I hadn't been using any framework, just bare java in eclipse with tomcat 7.0
I've run into an error while trying to test authorization input. The app would check the login-password pair and then redirect using RequestDispatcher.forward() or RequestDispatcher.include() methods. But when executing them it throws an error with the following stack trace:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at entryPoint.Dispatcher.dispatch(Dispatcher.java:166)
at entryPoint.Dispatcher.service(Dispatcher.java:49)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at com.meterware.servletunit.InvocationContextImpl.service(InvocationContextImpl.java:76)
at com.meterware.servletunit.ServletUnitClient.newResponse(ServletUnitClient.java:126)
at com.meterware.httpunit.WebClient.createResponse(WebClient.java:647)
at com.meterware.httpunit.WebWindow.getResource(WebWindow.java:220)
at com.meterware.httpunit.WebWindow.getSubframeResponse(WebWindow.java:181)
at com.meterware.httpunit.WebWindow.getResponse(WebWindow.java:158)
at com.meterware.httpunit.WebWindow.updateWindow(WebWindow.java:199)
at com.meterware.httpunit.WebWindow.getSubframeResponse(WebWindow.java:183)
at com.meterware.httpunit.WebWindow.getResponse(WebWindow.java:158)
at com.meterware.httpunit.WebClient.getResponse(WebClient.java:122)
at test.Authorization.testAuthCorrectInput_WrongPassword(Authorization.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.servlet.ServletException: java.lang.AbstractMethodError: com.meterware.servletunit.ServletUnitServletContext.getClassLoader()Ljava/lang/ClassLoader;
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:343)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at com.meterware.servletunit.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:54)
at controllers.Auth.index(Auth.java:78)
... 44 more
Caused by: java.lang.AbstractMethodError: com.meterware.servletunit.ServletUnitServletContext.getClassLoader()Ljava/lang/ClassLoader;
at org.apache.jasper.compiler.TagPluginManager.init(TagPluginManager.java:72)
at org.apache.jasper.compiler.TagPluginManager.apply(TagPluginManager.java:56)
at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:240)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:373)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:353)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:340)
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:646)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:357)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
... 47 more
The first block represents an invocation error caught by central controller (Dispatcher) servlet while invoking method in which an AbstractMethodError had been thrown. The second and third ones are about that error.
The code of the test method is as follows:
#Test
public void testAuthIncorrectInput_Long() throws Exception {
WebRequest request = new PostMethodWebRequest("http://localhost:8080/CenralReportDL/Dispatcher?query=auth");
String longString = new String();
for (int i = 0; i < 52; i++) {
longString += "aA_ba";
}
request.setParameter("username", longString);
request.setParameter("password", longString);
WebResponse response = client.getResponse(request);
assertNotNull("No response received", response);
}
How can I get rid of this error? Is there a workaround? Should I maybe use some other means of servlet testing?
Also please do not suggest framework-specific testing utils such as strutstest, I want an actual solution for bare java web application.
UPDATE: In response to #JekinKalariya - I had a JasperException before. It complained about files not being in /WEB-INF folder, but due to my project structure they all were in /WebContent/WEB-INF. I was so frustrated because of that I just copied entire folder. Silly thing to do. I deleted it and now I'm back to that JasperException.
UPDATE: Now, I've done some research and found some answers on this issue. Didn't work for me though. I also found a suggestion to change a target runtime to J2EE Preview, which raised a different kind of exception:
com.meterware.httpunit.HttpNotFoundException: Error on HTTP request: 404 java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet [http://localhost/WEB-INF/jsp/auth.jsp]
I sure hope you can help, I am getting towards the end of my rope. I posted this question yesterday but was quickly down-voted because I referred to what I was doing as Distance Matrix API and it was immediately assumed I had simply enabled the wrong API in google. I have now enabled many more APIs than I would ever need and am still getting the same IllegalAccessError:
May 06, 2015 12:48:16 PM com.google.maps.GeoApiContext setQueryRateLimit
INFO: Configuring rate limit at QPS: 10, minimum delay 50ms between requests
Exception in thread "AWT-EventQueue-0" java.lang.IllegalAccessError: tried to access class com.squareup.okhttp.Dispatcher from class com.google.maps.GeoApiContext
at com.google.maps.GeoApiContext.setQueryRateLimit(GeoApiContext.java:224)
at com.google.maps.GeoApiContext.setQueryRateLimit(GeoApiContext.java:210)
at com.google.maps.GeoApiContext.<init>(GeoApiContext.java:56)
at budgetrouting.MapPane.<init>(MapPane.java:27)
at budgetrouting.BudgetRouting$1.run(BudgetRouting.java:19)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Process exited with exit code 0.
My code:
GeoApiContext context = new GeoApiContext();
context.setApiKey(APIKey);
GeocodingResult[] results;
try {
results = GeocodingApi.geocode(context, "1600 Amphitheatre Parkway Mountain View, CA 94043").await();
System.out.println(results[0].formattedAddress);
} catch (Exception e) {
e.printStackTrace();
}
I have read every scrap of information on this error and how it relates to google api, but so far I don't have any definitive answers. I think that the fact that it is an error and not an exception means that it may not have anything to do with my access rights, especially since the error occurs the line before I set my API key. Since the definition of IllegalAccessError states "this error can only occur at run time if the definition of a class has incompatibly changed," I will include my dependencies:
google-maps-services-0.1.1.jar
okhttp-1.2.1-jar-with-dependencies.jar
I have checked okhttp for integrity and the class mentioned in the error does exist. I am using Oracle JDeveloper 12c. No Maven-type helper was used.
Just for completeness sake, these are the APIs I have enabled:
BigQuery API
Debuglet Controller API
Directions API
Distance Matrix API
Elevation API
Geocoding API
Google Cloud Logging API
Google Cloud SQL
Google Cloud Storage
Google Cloud Storage JSON API
Google Maps Embed API
Google Maps Engine API
Time Zone API
Any ideas? Thanks!
The reason I was getting the above error was that google-maps-services-0.1.1.jar requires okhttp 2.0.0, not okhttp-1.2.1-jar-with-dependencies.jar, along with a few other things. This was a result of not using a Maven-like application.
I work with these libraries:
google-maps-services-0.1.1.jar -
okhttp-2.0.0.jar -
okio-1.11.0.jar -
Example code:
public String obtenerLatitudLongitud (String direccion) throws Exception{
try {
GeoApiContext context = new GeoApiContext().setApiKey(this.propiedades.get(ConstantesApi.KEY_MAPS_GOOGLE));
context.setQueryRateLimit(50);
GeocodingResult[] results = GeocodingApi.geocode(context,direccion).await();
latLong = results[0].geometry.location.toString();
logger.debug("Latitud, longitud : " + latLong);
} catch (Exception e) {
logger.error("Error Normalizando la direccion : " + direccion + " " + e.getMessage());
}
return latLong;
}
Until now we used JBoss AS 7.1 which has a tomcat as front-server. We now upgraded to Wildfly (JBoss 8.0) which ships with undertow as a tomcat replacement.
For our filedownloads, we are reading the input stream of the file, and writing this to the external context's response output stream. This worked well in JBoss AS 7.1 - even for large files. In Undertow WE receive the following exception even for pretty "small" files:
13:04:43,292 ERROR [io.undertow.request] (default task-15) Blocking request failed HttpServerExchange{ GET /project/getFile.xhtml}: java.lang.RuntimeException: org.xnio.channels.FixedLengthOverflowException
at io.undertow.servlet.spec.HttpServletResponseImpl.responseDone(HttpServletResponseImpl.java:527)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:287)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:168)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_51]
at java.lang.Thread.run(Thread.java:744) [rt.jar:1.7.0_51]
Caused by: org.xnio.channels.FixedLengthOverflowException
at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.write(AbstractFixedLengthStreamSinkConduit.java:97)
at org.xnio.conduits.Conduits.writeFinalBasic(Conduits.java:132) [xnio-api-3.2.0.Final.jar:3.2.0.Final]
at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.writeFinal(AbstractFixedLengthStreamSinkConduit.java:137)
at org.xnio.conduits.ConduitStreamSinkChannel.writeFinal(ConduitStreamSinkChannel.java:104) [xnio-api-3.2.0.Final.jar:3.2.0.Final]
at io.undertow.channels.DetachableStreamSinkChannel.writeFinal(DetachableStreamSinkChannel.java:172)
at io.undertow.servlet.spec.ServletOutputStreamImpl.writeBufferBlocking(ServletOutputStreamImpl.java:580)
at io.undertow.servlet.spec.ServletOutputStreamImpl.close(ServletOutputStreamImpl.java:614)
at io.undertow.servlet.spec.HttpServletResponseImpl.closeStreamAndWriter(HttpServletResponseImpl.java:451)
at io.undertow.servlet.spec.HttpServletResponseImpl.responseDone(HttpServletResponseImpl.java:525)
... 9 more
The getFile.xhtml is invoking the download and the following code is used to copy the stream:
(Try, catch, logs and error handling removed to save some space)
public void downloadFile(FileEntity fileEntity) {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType(getMimeType(fileEntity.getFile()));
ec.setResponseContentLength(new Long(fileEntity.getFile().length()).intValue());
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + ConversionHelper.validateFilename(fileEntity.getDisplayFileName()) + "\"");
OutputStream output = ec.getResponseOutputStream();
FileInputStream fis = new FileInputStream(fileEntity.getFile());
IOUtils.copy(fis, output);
fc.responseComplete();
}
I noticed that removing the line
ec.setResponseContentLength(new Long(fileEntity.getFile().length()).intValue());
makes it work again. However the ResponseConentLength is "correct". Using
ec.setResponseContentLength(new Long(fileEntity.getFile().length()).intValue() + 9);
(note the +9) solves this. Using +8 -> FixedLengthOverflow, using +10 -> FixedLengthUnderflow
The +9 is independent of the filesize. Any idea? Looks strange to me...
If you call output.close() it should have the effect you are after. This looks like an issue with JSF, and not related to Undertow.
Found the problem.
It has to do with the change of the server engine. Just not sure if it is directly related to undertow, or more an error with wildfly / JSF (or if it was an error in Jboss and now is working correctly):
To invoke the download, we used something like this in the getFile.xhtml:
<f:metadata>
<f:viewParam name="fileId" required="true"
value="#{getFileController.fileId}"></f:viewParam>
</f:metadata>
<h:outputLabel value="#{getFileController.download()}" />
this would usually produce:
<label>value</label>
if the value of the label would be a string.
since we reset the response inside download(), <label> is removed again. Then, using a fixed response size that's equal the file-length and calling responseComplete() basically ommits the trailing </label>. Undertow however seems to ignore the responseComplete()-Call and tries to append </label> to the response, notices, that the end of the (fixed) response stream is reached, and therefore throws the mentioned exception.
That's why providing a size of +9 solves this error - but causes corrupt files, cause </label>\n will be appended to the file.
obviously the usage of an output label was bad practice there. But since we reseted and manually filled the response stream and called responseComplete() that was working fine.
the fix is obviously to not produce any (not required) html tags on that page:
<f:metadata>
<f:viewParam name="fileId" required="true"
value="#{getFileController.fileId}"></f:viewParam>
<f:event listener="#{getFileController.dlNow()}" type="preRenderView"></f:event>
</f:metadata>
Beside the bad design there - shouldn't call responseComplete() ommit any additional writing to the response stream, including any write ATTEMPTS?
The docu says:
Signal the JavaServer Faces implementation that the HTTP response for
this request has already been generated (such as an HTTP redirect),
and that the request processing lifecycle should be terminated as soon
as the current phase is completed.
So, if the Faces Implementation is told that the Response has been send - why would it try to append something?