AWS SDK is throwing SdkClientException - java

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.

Related

Google Pub Sub "Permission Denied" for project owner account

I've been trying to get the Google Pub/Sub Java libraries to work using the Quickstart guides. None of them work as written, at least not for me. I'm working in IntelliJ, Maven framework, OSX, Java 8.
Take this example. I followed all the steps: Created a service account as Project Owner, installed the Gcloud SDK, set my GOOGLE_APPLICATIONS_CREDENTIALS envvar, and found that everything was hunky dory from the command line: I could create topics, publish messages, whatever I wanted.
Then when I tried to run the sample code:
import com.google.api.gax.rpc.ApiException;
import com.google.cloud.ServiceOptions;
import com.google.cloud.pubsub.v1.TopicAdminClient;
import com.google.pubsub.v1.ProjectTopicName;
public class CreateTopicExample {
/**
* Create a topic.
*
* #param args topicId
* #throws Exception exception thrown if operation is unsuccessful
*/
public static void main(String... args) throws Exception {
// Your Google Cloud Platform project ID
String projectId = ServiceOptions.getDefaultProjectId();
// Your topic ID, eg. "my-topic"
String topicId = args[0];
// Create a new topic
ProjectTopicName topic = ProjectTopicName.of(projectId, topicId);
try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
topicAdminClient.createTopic(topic);
} catch (ApiException e) {
// example : code = ALREADY_EXISTS(409) implies topic already exists
System.out.print(e.getStatusCode().getCode());
System.out.print(e.isRetryable());
}
System.out.printf("Topic %s:%s created.\n", topic.getProject(), topic.getTopic());
}
}
It throws the ApiException PERMISSION_DENIED. The full stacktrace:
com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: User not authorized to perform this action.
at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:55)
at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:72)
at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:60)
at com.google.api.gax.grpc.GrpcExceptionCallable$ExceptionTransformingFuture.onFailure(GrpcExceptionCallable.java:95)
at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:61)
at com.google.common.util.concurrent.Futures$4.run(Futures.java:1123)
at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:435)
at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:900)
at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:811)
at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:675)
at io.grpc.stub.ClientCalls$GrpcFuture.setException(ClientCalls.java:492)
at io.grpc.stub.ClientCalls$UnaryStreamToFuture.onClose(ClientCalls.java:467)
at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41)
at io.grpc.internal.CensusStatsModule$StatsClientInterceptor$1$1.onClose(CensusStatsModule.java:684)
at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:41)
at io.grpc.internal.CensusTracingModule$TracingClientInterceptor$1$1.onClose(CensusTracingModule.java:391)
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:475)
at io.grpc.internal.ClientCallImpl.access$300(ClientCallImpl.java:63)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:557)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$600(ClientCallImpl.java:478)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:590)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: io.grpc.StatusRuntimeException: PERMISSION_DENIED: User not authorized to perform this action.
at io.grpc.Status.asRuntimeException(Status.java:526)
... 19 more
The debugger tells me the projectId is set for the correct default project for that service account, so the service account is connected. And, as I said, I verified from the console that the permissions are in fact set to Project:Owner for that service account. So ... why the permission denied?
Thanks in advance for reading gnarly stack traces on my behalf.
Since you are running with no problem with gcloud this must be a problem with IntelliJ. You should check whether you need to start IntelliJ via shell (as described in this article) or set the GOOGLE_APPLICATIONS_CREDENTIALS variable in IntelliJ as described here.

JDK 7/JavaFX 2 application on Mac OSX El Capitan

I've just upgraded to El Capitan and I'm running into problems starting a custom JavaFX2 application running under JDK1.7.0u79 (the latest available from Oracle).
When starting the app, I'm getting this Exception:
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:403)
at com.sun.javafx.application.LauncherImpl.access$000(LauncherImpl.java:47)
at com.sun.javafx.application.LauncherImpl$1.run(LauncherImpl.java:115)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:191)
at javafx.scene.control.Control.loadClass(Control.java:115)
at javafx.scene.control.Control.loadSkinClass(Control.java:1021)
at javafx.scene.control.Control.access$500(Control.java:70)
at javafx.scene.control.Control$12.invalidated(Control.java:972)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:127)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:161)
at com.sun.javafx.css.StyleableStringProperty.set(StyleableStringProperty.java:71)
at javafx.scene.control.Control$12.set(Control.java:964)
at com.sun.javafx.css.StyleableStringProperty.applyStyle(StyleableStringProperty.java:59)
at com.sun.javafx.css.StyleableStringProperty.applyStyle(StyleableStringProperty.java:31)
at com.sun.javafx.css.StyleableProperty.set(StyleableProperty.java:70)
at com.sun.javafx.css.StyleHelper.transitionToState(StyleHelper.java:900)
at javafx.scene.Node.impl_processCSS(Node.java:7418)
at javafx.scene.Parent.impl_processCSS(Parent.java:1146)
at javafx.scene.control.Control.impl_processCSS(Control.java:1154)
at javafx.scene.Parent.impl_processCSS(Parent.java:1153)
at javafx.scene.Parent.impl_processCSS(Parent.java:1153)
at javafx.scene.Node.processCSS(Node.java:7386)
at javafx.scene.Scene.doCSSPass(Scene.java:454)
at javafx.scene.Scene.preferredSize(Scene.java:1468)
at javafx.scene.Scene.impl_preferredSize(Scene.java:1535)
at javafx.stage.Window$9.invalidated(Window.java:717)
at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:127)
at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:161)
at javafx.stage.Window.setShowing(Window.java:781)
at javafx.stage.Window.show(Window.java:796)
at javafx.stage.Stage.show(Stage.java:233)
at au.com.religaresecurities.trademax.client.Start.start(Start.java:131)
at com.sun.javafx.application.LauncherImpl$5.run(LauncherImpl.java:319)
at com.sun.javafx.application.PlatformImpl$5.run(PlatformImpl.java:219)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:182)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:179)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
Caused by: java.lang.NullPointerException
at com.sun.t2k.MacFontFinder.initPSFontNameToPathMap(MacFontFinder.java:339)
at com.sun.t2k.MacFontFinder.getFontNamesOfFontFamily(MacFontFinder.java:390)
at com.sun.t2k.T2KFontFactory.getFontResource(T2KFontFactory.java:233)
at com.sun.t2k.LogicalFont.getSlot0Resource(LogicalFont.java:184)
at com.sun.t2k.LogicalFont.getSlotResource(LogicalFont.java:228)
at com.sun.t2k.CompositeStrike.getStrikeSlot(CompositeStrike.java:86)
at com.sun.t2k.CompositeStrike.getMetrics(CompositeStrike.java:132)
at com.sun.javafx.font.PrismFontUtils.getFontMetrics(PrismFontUtils.java:31)
at com.sun.javafx.font.PrismFontLoader.getFontMetrics(PrismFontLoader.java:466)
at javafx.scene.text.Text.<init>(Text.java:153)
at javafx.scene.text.Text.<init>(Text.java:162)
at com.sun.javafx.scene.control.skin.ProgressIndicatorSkin.<clinit>(ProgressIndicatorSkin.java:78)
... 37 more
I can't just migrate the app to Java 8, so any help is much appreciated.
Update
I've been able to get the app running again by adding this to the start of my main method. Any better solutions out there?
try {
Class<?> macFontFinderClass = Class.forName("com.sun.t2k.MacFontFinder");
Field psNameToPathMap = macFontFinderClass.getDeclaredField("psNameToPathMap");
psNameToPathMap.setAccessible(true);
psNameToPathMap.set(null, new HashMap<String, String>());
} catch (Exception e) {
// ignore
}
After more than a week with that in an extensive enterprise application, I haven't noticed any problems in the UI.
For the lack of a better solution, I'm accepting my update above as answer. Maybe it helps someone...
I've been able to get the app running again by adding this to the start of my main method.
try {
Class<?> macFontFinderClass = Class.forName("com.sun.t2k.MacFontFinder");
Field psNameToPathMap = macFontFinderClass.getDeclaredField("psNameToPathMap");
psNameToPathMap.setAccessible(true);
psNameToPathMap.set(null, new HashMap<String, String>());
} catch (Exception e) {
// ignore
}
This isn't a direct answer, however I thought it important to pass on that this bug has been identified and fixed in an upcoming Java release. See https://bugs.openjdk.java.net/browse/JDK-8143907
I had the same problem. I changed the Text to a Label. I'm not sure it's possible in your case.

BigQuery - How to set read timeout in the Java client library

I am using Spark to load some data into BigQuery. The idea is to read data from S3 and use Spark and BigQuery client API to load data. Below is the code that does the insert into BigQuery.
val bq = createAuthorizedClientWithDefaultCredentialsFromStream(appName, credentialStream)
val bqjob = bq.jobs().insert(pid, job, data).execute() // data is a InputStream content
With this approach, I am seeing lot of SocketTimeoutException.
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.read(InputRecord.java:503)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:911)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:703)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1534)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at com.google.api.client.http.javanet.NetHttpResponse.<init>(NetHttpResponse.java:37)
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:94)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:972)
at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequestWithoutGZip(MediaHttpUploader.java:545)
at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequest(MediaHttpUploader.java:562)
at com.google.api.client.googleapis.media.MediaHttpUploader.resumableUpload(MediaHttpUploader.java:419)
at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:336)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:427)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
Looks like the delay in reading from S3 causes Google http-client to timeout. I wanted to increase the timeout and tried the below options.
val req = bq.jobs().insert(pid, job, data).buildHttpRequest()
req.setReadTimeout(3 * 60 * 1000)
val res = req.execute()
But this causes a Precondition failure in BigQuery. It expects the mediaUploader to be null, not sure why though.
Exception in thread "main" java.lang.IllegalArgumentException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:76)
at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:37)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequest(AbstractGoogleClientRequest.java:297)
This caused me to try the second insert API on BigQuery
val req = bq.jobs().insert(pid, job).buildHttpRequest().setReadTimeout(3 * 60 * 1000).setContent(data)
val res = req.execute()
And this time it failed with a different error.
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0: ",
"reason" : "invalid"
} ],
"message" : "Job configuration must contain exactly one job-specific configuration object (e.g., query, load, extract, spreadsheetExtract), but there were 0: "
}
Please suggest me how I can set the timeout. Also point me if I am doing something wrong.
I'll answer the main question from the title: how to set timeouts using the Java client library.
To set timeouts, you need a custom HttpRequestInitializer configured in your client. For example:
Bigquery.Builder builder =
new Bigquery.Builder(new UrlFetchTransport(), new JacksonFactory(), credential);
final HttpRequestInitializer existing = builder.getHttpRequestInitializer();
builder.setHttpRequestInitializer(new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
existing.initialize(request);
request
.setReadTimeout(READ_TIMEOUT)
.setConnectTimeout(CONNECTION_TIMEOUT);
}
});
Bigquery client = builder.build();
I don't think this will solve all the issues you are facing. A few ideas that might be helpful, but I don't fully understand the scenario so these may be off track:
If you are moving large files: consider staging them on GCS before loading them into BigQuery.
If you are using media upload to send the data with your request: these can't be too large or you risk timeouts or network connection failures.
If you are running an embarrassingly parallel data migration, and the data chunks are relatively small, bigquery.tabledata.insertAll may be more appropriate for large fan-in scenarios like this. See https://cloud.google.com/bigquery/streaming-data-into-bigquery for more details.
Thanks for the question!

How to fix java heap space on websphere when sending invalid xml

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

How to catch "Unable to sendViaPost to url"?

I am running two axis2 services which communicate with each other. On every service startup I get this error:
2014-02-24 13:02:31,258 [INFO ] HTTPSender - Unable to sendViaPost to url[http://127.0.0.1:8081/axis2/services/MYSERVICE1.MYSERVICE1HttpSoap12Endpoint/]
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.commons.httpclient.protocol.ReflectionSocketFactory.createSocket(ReflectionSocketFactory.java:140)
at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:125)
at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:621)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:193)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406)
at org.apache.axis2.description.OutInAxisOperationClient$NonBlockingInvocationWorker.run(OutInAxisOperation.java:446)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Since this error is not important, I would like to catch it and to print some better error message instead of the whole stack trace. Where do I catch this error?
Looking at the stack trace, I don't think you can catch it. Catching it would require that you own code somewhere in the Thread where the exception is being thrown.
Looking at the lowest stack in the trace shows this:
at java.lang.Thread.run(Thread.java:724)
To me this says that the exception is occurring in a thread most likely started by Axis. Because of this you can't catch it and show an error message.
If this is expected behavior, the best you can do is to configure your logging framework not to show INFOs from Axis. Be aware that this may mean you'll also miss more useful error messages as well.
All in all, I would focus on how to solve the "Unable to sendViaPost" from happening rather than suppressing the logging statement.
To answer your comment question: As you can see from the stack trace, the exception is not caught by any client code but is bubbled up to Thread itself. This is the stopping point for an Exception and where it stops. If you were going to catch it you'd have to have code in its call stack (which you don't, since when the thread is created by Axis a new call stack is created for the new thread Axis starts).
Read more here. The only difference in your case is that since the exception is not thrown on the main thread the program doesn't exit, but the thread where the exception occurs is terminated.
To sum it up: You have no code in the call stack and therefore cannot catch the exception. The only other option is to turn of INFO statements for Axis.
If I am understanding the question properly you're attempting to catch something that is not the exception that is being thrown.
This:
HTTPSender - Unable to sendViaPost to url[http://127.0.0.1:8081/axis2/services/MYSERVICE1.MYSERVICE1HttpSoap12Endpoint/]
is what is being attempted. When it failed it's throwing a ConnectException.
Which you can simply catch with
try{
//Code that Makes the Connection
}
catch (ConnectException e)
{
e.printStackTrace();//Or What ever your message may be
}
Without seeing some code it's impossible to give a definitive answer. But this likely will solve the problem.
One Caveat, if you do catch a ConnectException to suppress it, you could suppress when there actually is a problem that would also throw a ConnectException.
If this is happening when you are starting up the server you might want to check why this is happening before trying to suppress it.
If it's refusing the connection that you are attempting you might want to ensure where it is connecting to has an available socket to connect to.
2014-02-24 13:02:31,258 [INFO] HTTPSender - Unable to
sendViaPost to
url[http://127.0.0.1:8081/axis2/services/MYSERVICE1.MYSERVICE1HttpSoap12Endpoint/]
Well, if you look closely, the message which you are trying to catch isn't an ERROR at all. It's an INFO log generated from HTTPSender. Only thing which you should catch in this entire stacktrace is java.net.ConnectException and check for message Connection refused.
You can make it easier for your clients though and provide a message, by wrapping the java.net.ConnectException with message Connection refused or throwing a custom exception with the original exception as the cause.
UPDATE
java.net.ConnectException is an elementary exception in network transactions. Generally standard libraries do not catch them unless there is something specific to be done.
In this case, if you are unable to catch hold of java.net.ConnectException, then you can look out to catch AxisFault thrown by org.apache.axis2.description.OutInAxisOperationClient.send.
Below snippet may be useful for you.
try {
...
} catch (RemoteException ex) {
if(ex instanceof AxisFault){
logger.error("Axis Fault error: " + ((AxisFault)ex).getFaultString());
throw new CustomExcpetion(" Custom Message ");
}
}
Also note that AxisFault is a subclass of java.rmi.RemoteException and this will not get caught when you use java.lang.Exception in a catch statement.
Shishir

Categories

Resources