I am making my first attempt at writing a BlackBerry App that consumes SOAP web services that embed JSON data, and have hit a challenge that's taking longer than I have to solve. I'd appreciate assistance on this. Thank you.
Below is the structure of the Web Service Request:
<logonrequest>
{
"userid":"username",
"password":"password",
"Timestamp":""
}
</logonrequest>
Below is the structure of the Web Service Response:
<return>
{
"userid":"username",
"displayName":"Firstname Lastname",
"accountBalance":0.0,
"statusCode":"0|SUCCESS",
"statusDesc":"Logon Success",
"sessionid":"12047CC560484D21BD328EC8F22814ED",
"lastTransactionTime":"20131130234326"
}
</return>
Below is my BlackBerry Java Code:
package com.abc.app;
import java.io.IOException;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.MainScreen;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransport;
import org.xmlpull.v1.XmlPullParserException;
import a1.org2b.json.me.JSONException;
import a1.org2b.json.me.JSONObject;
public class MySoapAttempt extends MainScreen {
String serviceUrl = "http://www.abcappserver.tk:30740/abcJSONWebApp/abcJSONWebServiceV1?wsdl";
String serviceNamespace = "http://webapps.abc.abcConnect.com/";
String soapAction = "http://webapps.abc.abcConnect.com/logonrequest";
HttpTransport transport = new HttpTransport(serviceUrl + "/;deviceside=false;ConnectionType=mds-public");
SoapObject rpc = new SoapObject(serviceNamespace, "logonrequest");
// SoapObject result;
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
public MySoapAttempt() {
envelope.bodyOut = rpc;
JSONObject container = new JSONObject();
try {
container.put("userid", "username");
container.put("password", "password");
container.put("Timestamp", "");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rpc.addProperty("logonrequest", container.toString());
envelope.setOutputSoapObject(rpc);
try {
envelope.dotNet = false;
envelope.encodingStyle = SoapSerializationEnvelope.XSD;
transport.debug = true;
transport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
transport.call(soapAction, envelope);
SoapPrimitive result = (SoapPrimitive)envelope.getResponse();
Dialog.alert(result.toString());
System.out.println("------=========-------- "+result);
} catch (IOException e) {
System.out.println("======= IOException =======");
System.out.println(e.getMessage());
e.printStackTrace();
} catch (XmlPullParserException e) {
System.out.println("======= XmlPullParserException =======");
System.out.println(e.getMessage());
System.out.println(e.toString());
e.printStackTrace();
} catch (Exception e) {
System.out.println("======= General Exception =======");
System.out.println(e.getMessage());
System.out.println(e.toString());
e.printStackTrace();
} finally {
System.out.println("=== >>> REQUEST: " + transport.requestDump);
System.out.println("===========================================");
System.out.println("=== >>> REQUEST: " + transport.responseDump);
add(new LabelField("Welcome To My SOAP Attempt"));
}
}
}
Below is the structure of the Web Service Console:
[127779.77] AM: Starting abc
[127779.79] AM: Started abc(483)
[127779.79] AM: Foreground is set: abc(483)
...
[127793.06] ======= XmlPullParserException =======
[127793.06] expected: END_TAG {http://schemas.xmlsoap.org/soap/envelope/}Body (position:END_TAG </{http://schema
[127793.06] s.xmlsoap.org/soap/envelope/}S:Fault>#1:324 in java.io.InputStreamReader#267621d3)
[127793.06] org.xmlpull.v1.XmlPullParserException: expected: END_TAG {http://schemas.xmlsoap.org/soap/envelope/}
[127793.06] Body (position:END_TAG </{http://schemas.xmlsoap.org/soap/envelope/}S:Fault>#1:324 in java.io.InputS
[127793.06] treamReader#267621d3)
[127793.06] No stack trace
[127793.06] === >>> REQUEST: <?xml version="1.0" encoding="UTF-8"?><v:Envelope xmlns:i="http://www.w3.org/2001/X
[127793.06] MLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/so
[127793.06] ap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/
[127793.06] envelope/"><v:Header /><v:Body><n0:logonrequest id="o0" c:root="1" xmlns:n0="http://webapps.abc.
[127793.06] abcConnect.com/"><logonrequest i:type="d:string">{"userid":"username","password":"password","Timesta
[127793.06] mp":""}</logonrequest></n0:logonrequest></v:Body></v:En
[127793.06] velope>
[127793.06]
[127793.06] ===========================================
[127793.07] === >>> REQUEST: <?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.o
[127793.07] rg/soap/envelope/"><S:Body><S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope"><faultcode>S
[127793.07] :Client</faultcode><faultstring>Cannot find dispatch me
[127793.07] thod for {http://webapps.abc.abcConnect.com/}logonrequest</faultstring></S:Fault></S:Body></S:E
[127793.07] nvelope>
I notice from the console output that my request string seems to be malformed. How can I have it send a request that looks exactly like the required sample request above? Thank you.
I can't answer this question from a SOAP perspective as I know nothing about SOAP. And I am not great on XML. But from an XML perspective, your XML appears to be badly formed. If you want to pass data that should NOT be interpreted as XML, then use CDATA. Otherwise the XML parser will try to interpret the JSON characters as XML which is it not.
For further information see here:
http://www.w3schools.com/xml/xml_cdata.asp
As I understood it, when you are using SOAP, you are expected to use XML, so another option would be to format your data for XML. It should be possible to create an equivalent XML structure to contain your JSON data and that will be parsed correctly.
Related
Reference: java.io.IOException: Attempted read from closed stream
Reference: https://github.com/karatelabs/karate/blob/master/karate-core/src/main/java/com/intuit/karate/http/ApacheHttpClient.java
KarateCore - class file: ApacheHttpClient.java is unable to process the Response its failing at the code line
CloseableHttpClient client = clientBuilder.build();
CloseableHttpResponse httpResponse;
byte [] bytes;
try {
httpResponse = client.execute(requestBuilder.build());
HttpEntity responseEntity = httpResponse.getEntity();
if (responseEntity == null || responseEntity.getContent() == null) {
bytes = Constants.ZERO_BYTES;
} else {
**InputStream is = responseEntity.getContent();**
bytes = FileUtils.toBytes(is);
}
request.setEndTimeMillis(System.currentTimeMillis());
} catch (Exception e) {
if (e instanceof ClientProtocolException && e.getCause() != null) { // better error message
throw new RuntimeException(e.getCause());
} else {
throw new RuntimeException(e);
}
}
The Code is failing at line InputStream is = responseEntity.getContent(); when trying to read from a closed stream. The exception message displayed
Error com.intuit.karate - Runtimejava.io.IOException: Attempted read from closed stream.
May be the InputStream need to updated.
I am able read the Http Response content using below code
BufferedReader br = new BufferedReader(
new InputStreamReader((httpResponse.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null){
output = br,readLine();
System.out.println(output);
}
Also the able to read the response using EntityUtils as a string content
String content = EntityUtils.toString(responseEntity);
System.out.println(content);
Not sure if i am missing something in the feature:scenario file response or the ApacheHttpClient.java file need to updated to read InputStream and then convert to bytes.
Feature: Hello
Scenario: Rest API Post
Given url 'some url path'
And header Content-Type = 'application/json'
And request { username: 'abc', password: 'pwd' }
When method POST
Then status 200
And print 'Response is:', response
The expected Response is a JSON format as:
{
"accessToken": "akjdoioikf",
"expires":"2020-01-29T01:09:48Z"
}
Any suggestions, appreciated!
Trying to hit Jersey multipart service with httpclient, and seeing some issues. Could you please share your insights to resolve this issue. Below I posted client code, service, stack trace.
Thanks for your support.
It works good when I use below client and register classes. Not finding any facility to register these classes for http client.
javax.ws.rs.client.Client
client.register(JacksonJsonProvider.class);
client.register(MultiPartFeature.class);
CLIENT CODE:
final String CONTENT_TYPE_MULTIPART = "multipart/related";
final String CONTENT_TYPE = "application/octet-stream";
final String BOUNDARY = "--upload_boundary--";
String responseStr = "";
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntityBuilder.addBinaryBody("file_upload", inputStream, ContentType.create(CONTENT_TYPE), "filename");
HttpPost httpPost = new HttpPost(finalURL);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_MULTIPART);//+";type="+CONTENT_TYPE+";boundary="+BOUNDARY);
httpPost.setEntity(multipartEntityBuilder.build());
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
responseStr = entity.toString();
RestHelper.verifyResponse(response, responseStr);
} catch (ClientProtocolException e) {
LOGGER.error("ClientProtocolException during upload",e);
} catch (IOException e) {
LOGGER.error("IOException during upload",e);
} finally {
response.close();
httpclient.close();
}
REST SERVICE:
#Consumes(MULTIPART_RELATED)
public String addDocument(MultiPart multipart)
STACKTRACE:
httpResponse :::::::::::::::::::: HttpResponseProxy{HTTP/1.1 400 Bad Request [Content-Type: text/html;charset=ISO-8859-1, $WSEP: , Content-Language: en-US, Transfer-Encoding: chunked, X-Cnection: Close, Date: Mon, 10 May 2021 11:50:32 GMT, Set-Cookie: dev-issapps.us=2036276652.6195.0000; path=/; Httponly] ResponseEntityProxy{[Content-Type: text/html;charset=ISO-8859-1,Chunked: true]}}
17:20:32.220 [main] ERROR us.dc.httpproxy.RestHelper - Response Error: RestException{us.dc.httpproxy.RestException
: HTTP/1.1 400 Bad Request', statusCode=400, detail='ResponseEntityProxy{[Content-Type: text/html;charset=ISO-8859-1,Chunked: true]}'}
17:20:32.221 [main] ERROR us.dc.httpproxy.RestClient - Exception in executeMultiPartRequest http://XXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXX/api/applications/GWEW/documents
RestException{ us.dc.httpproxy.RestException: HTTP/1.1 400 Bad Request', statusCode=400, detail='ResponseEntityProxy{[Content-Type: text/html;charset=ISO-8859-1,Chunked: true]}'}
Here is the solution, hope it helps somebody:
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13'
compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.3'
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
File file = new File("src/main/resources/48-1.jpg");
MultipartEntityBuilder entitybuilder = MultipartEntityBuilder.create();
entitybuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entitybuilder.addBinaryBody("image", new FileInputStream(file), ContentType.APPLICATION_OCTET_STREAM, file.getName());
entitybuilder.setContentType(ContentType.create("multipart/related"));
HttpEntity mutiPartHttpEntity = entitybuilder.build();
RequestBuilder reqbuilder = RequestBuilder.post(url);
reqbuilder.setEntity(mutiPartHttpEntity);
HttpUriRequest multipartRequest = reqbuilder.build();
HttpResponse httpresponse = httpclient.execute(multipartRequest);
System.out.println("response status = " + httpresponse.getStatusLine().getStatusCode());
System.out.println("filenet id = " + EntityUtils.toString(httpresponse.getEntity()));
}catch(Exception e) {
e.printStackTrace();
}
Considering the test07 stream is already created the following code snippet won't get response body in the exception stack trace.
try {
URI dataFlowUri = URI.create("http://localhost:9393");
DataFlowOperations dataFlowOperations = new DataFlowTemplate(dataFlowUri);
StreamDefinition streamDefinition = Stream.builder(dataFlowOperations)
.name("test07")
.definition("time|log")
.create();
}
catch (Exception ex){
ex.printStackTrace();
}
org.springframework.web.client.HttpClientErrorException$Conflict: 409 : [no body]
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:125)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:184)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:125)
at org.springframework.cloud.dataflow.rest.client.VndErrorResponseErrorHandler.handleError(VndErrorResponseErrorHandler.java:62)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:782)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:740)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:418)
at org.springframework.cloud.dataflow.rest.client.StreamTemplate.createStream(StreamTemplate.java:121)
at org.springframework.cloud.dataflow.rest.client.dsl.StreamDefinition.(StreamDefinition.java:60)
at org.springframework.cloud.dataflow.rest.client.dsl.Stream$StreamDefinitionBuilder.create(Stream.java:400)
on other hand when Post request this directly
http://localhost:9393/streams/definitions?name=test07&definition=time%20%7C%20log&description=test07
the response as follow with status code 409
[
{
"logref": "DuplicateStreamDefinitionException",
"message": "Cannot create stream test07 because another one has already been created with the same name"
}
]
I want to get response body when exception occur
so anyone can help if I'm missing something here?
I had to override the default rest template to get the response body as desired.
ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
RestTemplate restTemplate = new RestTemplate(factory);
URI dataFlowUri = URI.create("http://localhost:9393");
DataFlowOperations dataFlowOperations = new DataFlowTemplate(dataFlowUri, restTemplate);
StreamDefinition streamDefinition = Stream.builder(dataFlowOperations)
.name("test07")
.definition("time|log")
.create();
thanks
I am building simple chatting application using WebSocket using Eclipse and apache 7.x .However I am not able to compile my code cause it shows import javax.websocket cannot be resolved. After Googling a lot i found Link that shows external jar in application. I added a jar in my library section. It removed my current error but gave another. Now it showing WebSocket connection to 'ws://localhost:8080/WebSocket/socket' failed: Error during WebSocket handshake: Unexpected response code: 404
I'v tried a lot like adding servlet-api.jar to build path from apache lib. And also find some information like It provides also the javax.websocket-api-1.0.jar library so this is not needed in you application. You might need it at compile time but the server will provide it at runtime
Now I got stuck like in recursion. when I remove my jar got first error and when I add external jar then got second error. please help me in this issue cause we are developing mini project for real time collaborative editor and we are suppose to use websocket in it.
Now here is my code for websocket(not using maven):
WebSocket.java
package com.psl.service;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
#ServerEndpoint("/socket")
public class WebSocket {
Set<Session> sessionSet = Collections.synchronizedSet(new HashSet<>());
#OnOpen
public void onOpen(Session webSession) {
System.out.println("Opened");
sessionSet.add(webSession);
}
#OnMessage
public void onMessage(String message, Session webSession) throws IOException {
System.out.println("Got message "+message);
String username = (String)webSession.getUserProperties().get("username");
if(username==null) {
webSession.getUserProperties().put("username", message);
webSession.getBasicRemote().sendText(buildJSON(username, message));
}
else {
for(Session s : sessionSet) {
s.getBasicRemote().sendText(buildJSON(username, message));
}
}
}
private String buildJSON(String string, String string2) {
String jsonData="";
JSONObject obj=new JSONObject();
try {
obj.put("message",string + ":" + string2);
StringWriter out = new StringWriter();
JSONWriter jwriter = new JSONWriter(out);
jwriter.key(string).value(string2);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#OnClose
public void onClose() {
System.out.println("CLosed");
sessionSet.remove(sessionSet);
}
}
chat.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript">
var websocket = new WebSocket("ws://localhost:8080/WebSocketDemo/socket");
websocket.onmessage = function onMessage(message) {
var jsonData = JSON.parse(message.data);
if(jsonData.message != null) {
messageTextArea.value += jsonData.message + "\n";
}
}
function sendMessage() {
websocket.send(sendText.value);
sendText.value = "";
}
</script>
</head>
<body>
<textarea rows="30" cols="70" id="messageTextArea" ></textarea><br /><br />
<input id="sendText">
<input type="button" value="Send" onclick="sendMessage()">
</body>
</html>
I got answer for this query. This is because the added jar overrides my internal jars in apache tomcat. And I am using older tomcat that have not websocket-api.jar
So My solution for this problem is either use glashfish 4.x or else use apache tomcat 8.x that gives us required jar to run websocket. No need to add any extra websocket api jar.
I have a button in the UI that calls method for downloading a file which takes an InpuStream type. This is my code
<p:commandButton value="Download" actionListener="#{cc.attrs.noteAndFileBean.downloadFileAttached(noteAndFile)}" />
and the bean
public void downloadFileAttached(final GridFSDBFile noteAndFile)
{
try
{
PortletResponse portletResponse = (PortletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
HttpServletResponse response = PortalUtil.getHttpServletResponse(portletResponse);
response.setContentType(noteAndFile.getContentType());
response.setHeader("Content-Disposition", "attachment; filename=\"" + noteAndFile.getFilename());
response.setHeader("Content-Transfer-Encoding", "binary");
response.getOutputStream().write(IOUtils.toByteArray(noteAndFile.getInputStream()));
response.flushBuffer();
}
catch (IOException excpetion)
{
LOGGER.error("An error occurred downloading the file: " + excpetion.getMessage(), excpetion);
showMessage(ERROR, "Problemas al descargar el archivo");
}
}
The GridFSDBFile type is an object that stores files in mongo then for get the InputStream I call getInputStream() then I pass it to byte array.
When I call this method I receive a big exception (Part of it)
Caused by: java.lang.IllegalStateException
at com.liferay.portal.servlet.filters.gzip.GZipResponse.getWriter(GZipResponse.java:150)
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:105)
at com.liferay.portal.kernel.servlet.MetaInfoCacheServletResponse.getWriter(MetaInfoCacheServletResponse.java:315)
at com.liferay.portlet.MimeResponseImpl.getWriter(MimeResponseImpl.java:102)
at com.liferay.faces.bridge.context.BridgeContextImpl.getResponseOutputWriter(BridgeContextImpl.java:1197)
at com.liferay.faces.bridge.context.BridgeContextWrapper.getResponseOutputWriter(BridgeContextWrapper.java:251)
at com.liferay.faces.bridge.context.ExternalContextCompat_2_0_Impl.getResponseOutputWriter(ExternalContextCompat_2_0_Impl.java:629)
at com.sun.faces.context.PartialViewContextImpl.createPartialResponseWriter(PartialViewContextImpl.java:429)
at com.sun.faces.context.PartialViewContextImpl.access$300(PartialViewContextImpl.java:72)
at com.sun.faces.context.PartialViewContextImpl$DelayedInitPartialResponseWriter.getWrapped(PartialViewContextImpl.java:573)
at com.liferay.faces.util.context.PartialResponseWriterWrapper.<init>(PartialResponseWriterWrapper.java:31)
at com.liferay.faces.util.context.PartialViewContextCleanupImpl$PartialResponseWriterCleanupImpl.<init>(PartialViewContextCleanupImpl.java:198)
at com.liferay.faces.util.context.PartialViewContextCleanupImpl.getPartialResponseWriter(PartialViewContextCleanupImpl.java:177)
at org.primefaces.context.PrimePartialViewContext.getPartialResponseWriter(PrimePartialViewContext.java:71)
at com.sun.faces.context.AjaxExceptionHandlerImpl.handlePartialResponseError(AjaxExceptionHandlerImpl.java:197)
at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:124)
at javax.faces.context.ExceptionHandlerWrapper.handle(ExceptionHandlerWrapper.java:97)
at com.liferay.faces.bridge.context.ExceptionHandlerAjaxImpl.handle(ExceptionHandlerAjaxImpl.java:85)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at com.liferay.faces.bridge.BridgePhaseResourceImpl.execute(BridgePhaseResourceImpl.java:107)
... 136 more
How can I download the file?
I found the solution, It's important get Liferay's ServletResponse and pass it the InputStream in byte array.
public StreamedContent getDownloadFileStreamContent(final GridFSDBFile noteAndFile)
{
try
{
PortletResponse portletResponse = (PortletResponse) FacesContext.getCurrentInstance().getExternalContext()
.getResponse();
HttpServletResponse res = PortalUtil.getHttpServletResponse(portletResponse);
res.setHeader("Content-Disposition", "attachment; filename=\"" + noteAndFile.getFilename() + "\"");//
res.setHeader("Content-Transfer-Encoding", "binary");
res.setContentType(noteAndFile.getContentType());
res.getOutputStream().write(IOUtils.toByteArray(noteAndFile.getInputStream()));
res.flushBuffer();
showMessage(SUCCESS, "Archivo descargado");
}
catch (IOException ioe)
{
showMessage(ERROR, "Problemas al descargar el archivo");
LOGGER.error("An error occurred uploading the file: " + ioe.getMessage(), ioe);
}
return null;
}
Adicionaly I use the primefaces's component
<p:commandButton value="Nuevo Download" ajax="false" update="growl">
<p:fileDownload value="#{cc.attrs.noteAndFileBean.getDownloadFileStreamContent(noteAndFile)}" />
</p:commandButton>