Trying to fetch the response using spring web client, but the result response is getting truncated as the response size is more than that of string class. Is there any other way to get the response without being truncated?
LinkedMultiValueMap<String, Object> requestMap = new LinkedMultiValueMap<String, Object>();
//String response = "";
try{
File tempFile = File.createTempFile("ccda", "File");
FileOutputStream out = new FileOutputStream(tempFile);
IOUtils.copy(ccdaFile.getInputStream(), out);
requestMap.add("ccdaFile", new FileSystemResource(tempFile));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity =
new HttpEntity<LinkedMultiValueMap<String, Object>>(requestMap, headers);
RestTemplate restTemplate = new RestTemplate();
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
formConverter.setCharset(Charset.forName("UTF8"));
restTemplate.getMessageConverters().add(formConverter);
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
String response = restTemplate.postForObject("localhost:8080",
requestEntity, String.class);
tempFile.delete();
}catch(Exception exc)
{
exc.printStackTrace();
}
You may use an InputStream
I think you may do in this way:
InputStream is = rt.execute("localhost:8080", HttpMethod.POST, requestCallback, responseExtractor);
Where requestCallback is an implementation of org.springframework.web.client.RequestCallback like this one
public class MyRequestCallback implements RequestCallback
{
#Override
public void doWithRequest(ClientHttpRequest request) throws IOException
{
request.getHeaders().add(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE);
request.getHeaders().add(HttpHeaders.ACCEPT, MimeTypeUtils.APPLICATION_JSON_VALUE);
}
}
While responseExtractor may by an instance of this class
public class MyResponseExtractor implements ResponseExtractor<InputStream>
{
#Override
public Boolean extractData(ClientHttpResponse response) throws IOException
{
HttpStatus status = response.getStatusCode();
switch (status)
{
case OK:
return response.getBody();
default:
return null;
}
}
}
Once obtained the InputStream you can manage it
Hope it is usefull
Related
We are migrating to Redis from RabbitMQ in our microservice applications.
Here is our service activator
#ServiceActivator(inputChannel = ApplicationEventChannelNames.REMOTE_CHANNEL)
public void handleApplicationEvent(#Header(value = ApplicationEventHeaders.APPLICATION_EVENT) final ApplicationEvent event,
#Payload Object message) {
...
}
Initially we had a problem where we were losing application event in the SimpleMessageConverter. We solved it by implementing a CustomRedisMessageConverter and putting application event into the payload in the fromMessage method and retreiving it from payload and create a new message headers with application event in the toMessage method.
#Override
public Object fromMessage(Message<?> message, Class<?> targetClass) {
if (message.getHeaders().get(ApplicationEventHeaders.APPLICATION_EVENT) != null) {
Map<String, Object> map = new HashMap<>();
map.put("headers", ((ApplicationEvent) message.getHeaders().get(ApplicationEventHeaders.APPLICATION_EVENT)).getName());
map.put("payload", message.getPayload());
GenericMessage<Map<String, Object>> msg = new GenericMessage<>(map, message.getHeaders());
return super.fromMessage(msg, targetClass);
}
return super.fromMessage(message, targetClass);
}
#Override
public Message<?> toMessage(Object payload, MessageHeaders headers) {
try {
final Map<String, ?> message = new ObjectMapper().readValue((String) payload, new TypeReference<Map<String, ?>>() {});
if (message.get("headers") != null) {
final Map<String, Object> messageHeaders = new HashMap<>(headers);
messageHeaders.put(ApplicationEventHeaders.APPLICATION_EVENT, new ApplicationEvent((String) message.get("headers")));
return super.toMessage(message.get("payload"), new MessageHeaders(messageHeaders));
}
} catch (JsonProcessingException exception) {
/* Intentionally left blank */
}
return super.toMessage(payload, headers);
}
We are wondering if there is a better approach for doing this?
Lastly, payload in the service activator come as a LinkedHashMap but we want it to be an object. With RabbitMQ this was handled.
Is there any way to do the same in Redis? Or do we use headers to keep track of the type of a payload and manually convert them into an object?
UPDATE - REDIS Configuration
#Bean
public RedisInboundChannelAdapter applicationEventInboundChannelAdapter(#Value(value = "${com.xxx.xxx.xxx.integration.spring.topic}") String topic,
MessageChannel applicationEventRemoteChannel,
RedisConnectionFactory connectionFactory) {
final RedisInboundChannelAdapter inboundChannelAdapter = new RedisInboundChannelAdapter(connectionFactory);
inboundChannelAdapter.setTopics(topic);
inboundChannelAdapter.setOutputChannel(applicationEventRemoteChannel);
inboundChannelAdapter.setErrorChannel(errorChannel());
inboundChannelAdapter.setMessageConverter(new CustomRedisMessageConverter());
return inboundChannelAdapter;
}
#ServiceActivator(inputChannel = "errorChannel")
public void processError(MessageHandlingException exception) {
try {
logger.error(
"Could not process {}, got exception: {}",
exception.getFailedMessage().getPayload(),
exception.getMessage());
logger.error(
ExceptionUtils.readStackTrace(exception));
} catch (Throwable throwable) {
logger.error(
"Got {} during processing with message: {} ",
MessageHandlingException.class.getSimpleName(),
exception);
}
}
#Bean
#ServiceActivator(inputChannel = ApplicationEventChannelNames.LOCAL_CHANNEL)
public RedisPublishingMessageHandler redisPublishingMessageHandler(#Value(value = "${com.xxx.xxx.xxx.integration.spring.topic}") String topic,
RedisConnectionFactory redisConnectionFactory) {
final RedisPublishingMessageHandler redisPublishingMessageHandler = new RedisPublishingMessageHandler(redisConnectionFactory);
redisPublishingMessageHandler.setTopic(topic);
redisPublishingMessageHandler.setSerializer(new Jackson2JsonRedisSerializer<>(String.class));
redisPublishingMessageHandler.setMessageConverter(new CusomRedisMessageConverter());
return redisPublishingMessageHandler;
}
/*
* MessageChannel
*/
#Bean
public MessageChannel errorChannel() {
return new DirectChannel();
}
Redis does not support headers, so you have to embed them into a body. See EmbeddedJsonHeadersMessageMapper which could be supplied into that org.springframework.integration.support.converter.SimpleMessageConverter on both side.
I need to send a PUT Request to a server. The body requires a key which is a String and a value which has to be a JSONObject, with content type being x-www-form-urlencoded. I've attached the required PUT request of Postman, the code I'm using and the error I'm getting below. Please help!
private void modifyObject(String object, String objectId) throws JSONException {
/**PUT REQUEST*/
String putUrl = api.url;
Log.d("putUrl", putUrl);
JSONObject jsonObject = new JSONObject();
jsonObject.put(dateName, actualDate);
jsonObject.put(locationName,actualLocation);
jsonObject.put(status,actualStatus);
final String requestBody = "data=" + jsonObject;
Log.d("requestBody", requestBody);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.PUT, putUrl, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("Response", String.valueOf(response));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Content-type", "application/json");
headers.put("Authorization", accessToken);
return headers;
}
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=utf-8";
}
#Override
public byte[] getBody() {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
};
mRequestQueue.add(request);
}
W/System.err: com.android.volley.ParseError: org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
W/System.err: at com.android.volley.toolbox.JsonObjectRequest.parseNetworkResponse(JsonObjectRequest.java:90)
W/System.err: at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:143)
at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:111)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:90)
W/System.err: Caused by: org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
W/System.err: at org.json.JSON.typeMismatch(JSON.java:112)
at org.json.JSONObject.<init>(JSONObject.java:163)
at org.json.JSONObject.<init>(JSONObject.java:176)
W/System.err: at com.android.volley.toolbox.JsonObjectRequest.parseNetworkResponse(JsonObjectRequest.java:85)
write this
final String requestBody = jsonObject.toString();
instead of this
final String requestBody = "data=" + jsonObject;
I am not getting virtually any response.
This is for a school project, i am not getting any response from volley what so ever, please help.
I've tried different versions of Volley, I've tried adding internet access to the manifest, no help.
RequestQueue queue = Volley.newRequestQueue(this);
api();
public void api(){
String new_url = "http://api.myjson.com/bins/kp9wz";
System.out.println(new_url);
final JsonObjectRequest request = new
JsonObjectRequest(Request.Method.GET, new_url, null, new
Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("employees");
devices = new ArrayList<>();
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String deviceId = jsonObject.getString("firstname");
String deviceName = jsonObject.getString("age");
String deviceStatus = jsonObject.getString("mail");
System.out.println(jsonObject.getString("firstname"));
System.out.println(jsonObject.getString("age"));
System.out.println(jsonObject.getString("mail"));
devices.add(new
Device(deviceName,deviceStatus,deviceId));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("WTF");
}
});
}
ยดยดยด
I don't get anything
I expect it to save the data into the arraylist and sout, each field in the for loop
I was stupid enough to not att the request to a RequestQueue, I've solved it.
I'm trying to post to a server via Asynchronous Task and while converting Hashmap to String, this error occurred. What does that Error mean. Why does it occour ? How do I resolve this ?
here is my code:
public class NetworkAccess extends AsyncTask<HashMap<String,String>,Void,String> {
private URL url;
private HttpURLConnection con;
private OutputStream os;
#Override
protected String doInBackground(HashMap<String, String>... vals) {
String response = "";
try {
url = new URL("http://192.168.0.3/chow/user-login.php");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
con.setConnectTimeout(1000);
OutputStream os = con.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os,"UTF-8"));
String pd = getPostDataString(vals); //Error
writer.write(pd);
writer.flush();
writer.close();
BufferedInputStream bis = new BufferedInputStream(con.getInputStream());
BufferedReader r = new BufferedReader(new InputStreamReader(bis));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
response = total.toString();
}
catch (Exception e){
e.printStackTrace();
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.entrySet()){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
}
The error which you got shows that you're directly trying to create a array of HashMap, rather you can create just Array of String, iterate the Collection and insert the HashMap objects into it.
Inside the getPostDataString(), change the code to
StringBuilder[] sb = new StringBuilder[100];
and check if it works.
I would like mock DefaultHttpClient.java and execute method in AbstractHttpClient.java, DefaultHttpClient extends AbstractHttpClient java class, and execute method is final method, so i need to powermock to mock final method.
#RunWith(PowerMockRunner.class)
#PrepareForTest(DefaultHttpClient.class)
//#PrepareForTest(AbstractHttpClient.class)
public class RestClientTest {
DefaultHttpClient client;
RestClient restClient = new RestClient();
#Test
public void getAll() throws Exception{
client = PowerMockito.spy(new DefaultHttpClient());
//PowerMockito.mock(DefaultHttpClient.class);
//Mockito.mock(DefaultHttpClient.class);
HttpResponse response = PowerMockito.mock(HttpResponse.class);
MarketplaceTO sampleData = new MarketplaceTO();
sampleData.setName("name");
//String endpoint = "";
//ProtocolVersion protoCol = new ProtocolVersion("HTTP", 2, 1);
//StatusLine status = new BasicStatusLine(protoCol, HttpStatus.SC_OK, null);
//HttpResponse response = new BasicHttpResponse(status);
BasicHttpEntity entity = new BasicHttpEntity();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(sampleData);
oos.flush();
oos.close();
InputStream is = new ByteArrayInputStream(baos.toByteArray());
entity.setContent(is);
entity.setContentLength(is.available());
response.setEntity(entity);
//PowerMockito.doNothing().when((AbstractHttpClient)client).execute(Mockito.any(HttpUriRequest.class),Mockito.any(HttpContext.class));
PowerMockito.doReturn(response).when(client).execute(Mockito.any(HttpUriRequest.class));
//HttpGet getRequest = new HttpGet(endpoint);
//PowerMockito.when(client.execute(Mockito.any(HttpGet.class))).thenReturn(response);
//Mockito.stub(client.execute(getRequest)).toReturn(response);
//System.out.println("code "+response.getStatusLine().getStatusCode());
EMResponse<MarketplaceTO> responseData = restClient.getAll("", MarketplaceTO.class);
//System.out.println("name is "+responseData.getModelObject().getName());
Assert.assertEquals("name", responseData.getModelObject().getName());
}
}
and RestClient.java has
public <T> EMResponse<T> getAll(String entity, Class<T> entityClass) {
StringBuffer bufferedReader = null;
String output = "";
EMResponse<T> emResponse = null;
EMError emError = null;
ObjectMapper objectMapper = new ObjectMapper();
DefaultHttpClient httpClient = new DefaultHttpClient();
try {
bufferedReader = new StringBuffer();
String endpoint = /*EntityManagerProperties
.get(EntityManagerProperties.ENTITY_MANAGER_SERVICE_URL)
+ "/" + entity*/"http://google.com/abcd";
HttpGet getRequest = new HttpGet(endpoint);
HttpResponse response = httpClient.execute(getRequest);
System.out.println("code "+response.getStatusLine().getStatusCode());
return getEntityObjects(response, entityClass, true);
} catch (ClientProtocolException e) {
logger.error("Exception", e);
} catch (IOException e) {
logger.error("Exception", e);
} finally {
//httpClient.getConnectionManager().shutdown();
}
return emResponse;
}
if i call after mocking execute method, then also it is calling actual method.
Please help me. sorry for my english.
Reason why its calling original execute method is because you have used a constructor
DefaultHttpClient httpClient = new DefaultHttpClient();
in RestClient.java class.
so you should must mock the constructor and return your mocked object
Add this line
whenNew(DefaultHttpClient.class).withNoArguments().thenReturn(client);
before using:
PowerMockito.doReturn(response).when(client)
.execute(Mockito.any(HttpUriRequest.class));
and
Change #PrepareForTest(DefaultHttpClient.class) to #PrepareForTest({DefaultHttpClient.class, RestClient.class})
This will solve your problem.