How do I resolve an "Unknown Host Exception" when using Volley to interact with BigCommerce's Orders API endpoint? - android-volley

As far as I know, I am implementing Volley correctly, and I know for a fact that the API endpoint URL along with all the HTTP headers are 100% correct. Yet, when I try to GET the JSON from the endpoint, an Unknown Host Exception is thrown.
I used the BigCommerce Orders API reference and made multiple test queries, and it worked there, but there appears to be some kind of disconnect when ran on the emulator on Android studio. Is it possible that my business' WiFi and/or the emulator itself is causing this problem?
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.start();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(com.android.volley.Request.Method.GET,
URL, null, new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
parseOrders(response);
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Volley", error.getMessage());
Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
})
{
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("accept", "application/json");
params.put("content-type", "application/json");
params.put("x-auth-token", "myToken");
params.put("x-auth-client", "myClientID");
return params;
}
#Override
public String getBodyContentType() {
return "application/json";
}
};
requestQueue.add(jsonObjectRequest);

Related

Websocket not working with spring boot application and angular frontend

I looked and tried a lot but I can not find the cause of my problem...
I have a JHipster generated application which consists out of a spring boot application and an angular frontend and I want to use websockets for updates. For that I use Stomp and SockJs
The connection itself is already not working.
I get the following error:
WebSocket connection to 'ws://localhost:9000/updates/websocket/447/xxudq4ni/websocket' failed: WebSocket is closed before the connection is established.
This is the call to port 9000, which is then proxied to the actual backend under Port 8080.
If I call the backend under port 8080 directly, I get:
WebSocket connection to 'ws://localhost:8080/updates/websocket/156/mg0dspp2/websocket' failed: Error during WebSocket handshake: Unexpected response code: 200
I do not really see what the actual response is but I suppose it is the JHIpster error message "an error has occured" and this html is returned with a http statuscode of 200.
I'm out of ideas what the actual problem is... I followed this intro here and several others...
here is my backend:
WebsocketConfig:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
public static final String IP_ADDRESS = "IP_ADDRESS";
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
.addEndpoint("/updates/websocket")
//.setHandshakeHandler(defaultHandshakeHandler())
.setAllowedOrigins("*")
.withSockJS()
.setClientLibraryUrl("https://cdn.jsdelivr.net/npm/sockjs-client#1.5.0/dist/sockjs.min.js");
//.setInterceptors(httpSessionHandshakeInterceptor());
}
private DefaultHandshakeHandler defaultHandshakeHandler() {
return new DefaultHandshakeHandler() {
#Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
Principal principal = request.getPrincipal();
if (principal == null) {
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
principal = new AnonymousAuthenticationToken("WebsocketConfiguration", "anonymous", authorities);
}
return principal;
}
};
}
#Bean
public HandshakeInterceptor httpSessionHandshakeInterceptor() {
return new HandshakeInterceptor() {
#Override
public boolean beforeHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Map<String, Object> attributes
) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
attributes.put(IP_ADDRESS, servletRequest.getRemoteAddress());
}
return true;
}
#Override
public void afterHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Exception exception
) {}
};
}
}
Controller:
#Controller
public class UpdateController {
private static final Logger log = LoggerFactory.getLogger(UpdateController.class);
#MessageMapping("/updates/websocket")
#SendTo("/topic/trucks")
public UpdateDto send(UpdateDto dto) {
return dto;
}
}
Frontend:
connect(): void {
if (this.stompClient?.connected || this.called) {
return;
}
this.called = true;
// building absolute path so that websocket doesn't fail when deploying with a context path
let url = '/updates/websocket';
url = this.location.prepareExternalUrl(url);
var socket = new SockJS(url);
this.stompClient = Stomp.over(socket);
this.stompClient.connect({}, (frame) => {
this.connectionSubject.next();
this.sendActivity();
this.routerSubscription = this.router.events
.pipe(filter((event: Event) => event instanceof NavigationEnd))
.subscribe(() => this.sendActivity());
}, error => {
console.log(error);
});
}
Im on Windows and I use Chrome for the development. But it also does not work in FireFox, so I do not think it has something to do with the platform.
Any help would be very much appreciated. Thank you very much!

How to customize Spring boot controller API response for ZuulException

We are using Zuul, Eureka and spring boot application services for REST APIs.
Suppose my spring boot service is down and when I tried to access the API using Zuul API gateway, I am getting ZuulException and response is below :
{
"timestamp": "2018-10-12T14:29:09.632+0000",
"status": 500,
"error": "Internal Server Error",
"exception": "com.netflix.zuul.exception.ZuulException",
"message": "GENERAL"
}
I want to customize the response format like below:
{
"success": false,
"message": "Service is down. Please try later"
}
I tried to implement https://stackoverflow.com/a/39841785/5506061 but its not working for me.
Please suggest how to customize the response for ZuulException.
You can implement your own FallbackProvider and customize the response based on the cause if needed.
Something like :
#Component
public class CustomFallbackBasedOnCause implements FallbackProvider {
private static final String DEFAULT_MSG = "{\"success\": false,\"message\": \"Service is down. Please try later\"}";
#Override
public String getRoute() {
return "*"; // * = all routes
}
#Override
public ClientHttpResponse fallbackResponse(final Throwable cause) {
if (cause instanceof HystrixTimeoutException) {
return response(HttpStatus.GATEWAY_TIMEOUT);
} else {
return fallbackResponse();
}
}
#Override
public ClientHttpResponse fallbackResponse() {
return response(HttpStatus.INTERNAL_SERVER_ERROR);
}
private ClientHttpResponse response(final HttpStatus status) {
return new ClientHttpResponse() {
#Override
public HttpStatus getStatusCode() throws IOException {
return status;
}
#Override
public int getRawStatusCode() throws IOException {
return status.value();
}
#Override
public String getStatusText() throws IOException {
return status.getReasonPhrase();
}
#Override
public void close() {
}
#Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(DEFAULT_MSG.getBytes());
}
#Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
As you can see in the getRoute() method, you can specify if this customFallback will be used for all routes (return "*") or for a specific route.
In case you work with Registry service (e.g Eureka). You don’t specify the route URL but the service id instead. return "SERVICEID"

How to get Body Response when POST Multipart Request with Volley?

I'm working with post multipart request from android. And I follow this solution to upload image and succeed perfectly but the query is when I hit my API to upload image to server it returns OK response with a string just like that
I need this body response that is mentioned above. My volley code response only header data. My code is
VolleyMultipartRequest multipartRequest = new VolleyMultipartRequest(Request.Method.POST, url,
new Response.Listener<NetworkResponse>() {
#Override
public void onResponse(NetworkResponse response) {
Log.wtf("result: ", String.valueOf(response));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
...
}
}) {
#Override
protected Map<String, DataPart> getByteData() {
Map<String, DataPart> params = new HashMap<>();
...
return params;
}
};
Thanks

How to post an image to server in android

How do I upload an image to the Server? Both MultiPArtEntity and MultiPartEntityBuilder classes are deprecated in API level 23. Can we do this using HTTPUrlConnection or volley?
I suggest that you use OkHttp. More details about it you can find at the following:
OkHttp - An HTTP & SPDY client for Android and Java applications
Please refer to my basic sample code that uploads a PNG file from drawable folder to remote web service. Hope this helps!
...
mTextView = (TextView) findViewById(R.id.textView);
mHandler = new Handler(Looper.getMainLooper());
...
Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
if (drawable != null) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, stream);
final byte[] bitmapdata = stream.toByteArray();
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"ic_launcher.png\""),
RequestBody.create(MEDIA_TYPE_PNG, bitmapdata))
.build();
final Request request = new Request.Builder()
.url("http://myserver/api/files")
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(final Request request, final IOException e) {
Log.e(LOG_TAG, e.toString());
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, e.toString(), Toast.LENGTH_SHORT).show();
mTextView.setText(e.toString());
}
});
}
#Override
public void onResponse(Response response) throws IOException {
final String message = response.toString();
Log.i(LOG_TAG, message);
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
mTextView.setText(message);
}
});
}
});
}
Hello totally above answer is correct and accepted but here is the another solution the easiest way ever for posting image to the server:-
Using rest api from andoid spring framework in your android project just create new custom interface as below :-
#Rest(rootUrl ="BASE_URL", converters = {ByteArrayHttpMessageConverter.class,
FormHttpMessageConverter.class, StringHttpMessageConverter.class})
public interface CustomRest extends RestClientErrorHandling {
#Post("YourPostfixforUrl")
String _postImage(MultiValueMap<String, Object> multiValueMap);
}
Create your own RestErrorHandler using below code:-
#EBean
public class CustomRestErrorHandler implements RestErrorHandler
{
#Override
public void onRestClientExceptionThrown(NestedRuntimeException e)
{
Log.e("NestedRuntimeException ", "NestedRuntimeException :- " + e.toString());
}
}
On Your activity call bellow code :-
#AfterInject
public void afterInject() {
MultiValueMap<String, Object> ObjectMultiValueMap = new LinkedMultiValueMap<>();
ObjectMultiValueMap.add("yourImageKey", new FileSystemResource(new File("yourFilePath")));
doInBackground(myrest, ObjectMultiValueMap);
}
#Background
public void doInBackground(Myrest myrest, MultiValueMap<String, Object> multiValueMap) {
myrest.setRestErrorHandler(myErrorHandler);
}
Your Gradle will look like below:-
def AAVersion = '3.3.2'
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
apt "org.androidannotations:androidannotations:$AAVersion"
compile "org.androidannotations:androidannotations-api:$AAVersion"
compile 'org.springframework.android:spring-android-core:1.0.1.RELEASE'
compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE'}
NOTE:- Your activity Must be #Eactivity
--> I Guess androidannotation+rest is the best time saver and sincerely optimizing the code snippets!
Thanks

Spring MVC - RestTemplate launch exception when http 404 happens

I have a rest service which send an 404 error when the resources is not found.
Here the source of my controller and the exception which send Http 404.
#Controller
#RequestMapping("/site")
public class SiteController
{
#Autowired
private IStoreManager storeManager;
#RequestMapping(value = "/stores/{pkStore}", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public StoreDto getStoreByPk(#PathVariable long pkStore) {
Store s = storeManager.getStore(pkStore);
if (null == s) {
throw new ResourceNotFoundException("no store with pkStore : " + pkStore);
}
return StoreDto.entityToDto(s);
}
}
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException
{
private static final long serialVersionUID = -6252766749487342137L;
public ResourceNotFoundException(String message) {
super(message);
}
}
When i try to call it with RestTemplate with this code :
ResponseEntity<StoreDto> r = restTemplate.getForEntity(url, StoreDto.class, m);
System.out.println(r.getStatusCode());
System.out.println(r.getBody());
I receive this exception :
org.springframework.web.client.RestTemplate handleResponseError
ATTENTION: GET request for "http://........./stores/99" resulted in 404 (Introuvable); invoking error handler
org.springframework.web.client.HttpClientErrorException: 404 Introuvable
I was thinking I can explore my responseEntity Object and do some things with the statusCode. But exception is launch and my app go down.
Is there a specific configuration for restTemplate to not send exception but populate my ResponseEntity.
As far as I'm aware, you can't get an actual ResponseEntity, but the status code and body (if any) can be obtained from the exception:
try {
ResponseEntity<StoreDto> r = restTemplate.getForEntity(url, StoreDto.class, m);
}
catch (final HttpClientErrorException e) {
System.out.println(e.getStatusCode());
System.out.println(e.getResponseBodyAsString());
}
RESTTemplate is quite deficient in this area IMO. There's a good blog post here about how you could possibly extract the response body when you've received an error:
http://springinpractice.com/2013/10/07/handling-json-error-object-responses-with-springs-resttemplate
As of today there is an outstanding JIRA request that the template provides the possibility to extract the response body:
https://jira.spring.io/browse/SPR-10961
The trouble with Squatting Bear's answer is that you would have to interrogate the status code inside the catch block eg if you're only wanting to deal with 404's
Here's how I got around this on my last project. There may be better ways, and my solution doesn't extract the ResponseBody at all.
public class ClientErrorHandler implements ResponseErrorHandler
{
#Override
public void handleError(ClientHttpResponse response) throws IOException
{
if (response.getStatusCode() == HttpStatus.NOT_FOUND)
{
throw new ResourceNotFoundException();
}
// handle other possibilities, then use the catch all...
throw new UnexpectedHttpException(response.getStatusCode());
}
#Override
public boolean hasError(ClientHttpResponse response) throws IOException
{
return response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
|| response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR;
}
The ResourceNotFoundException and UnexpectedHttpException are my own unchecked exceptions.
The when creating the rest template:
RestTemplate template = new RestTemplate();
template.setErrorHandler(new ClientErrorHandler());
Now we get the slightly neater construct when making a request:
try
{
HttpEntity response = template.exchange("http://localhost:8080/mywebapp/customer/100029",
HttpMethod.GET, requestEntity, String.class);
System.out.println(response.getBody());
}
catch (ResourceNotFoundException e)
{
System.out.println("Customer not found");
}
Since it's 2018 and I hope that when people say "Spring" they actually mean "Spring Boot" at least, I wanted to expand the given answers with a less dust-covered approach.
Everything mentioned in the previous answers is correct - you need to use a custom ResponseErrorHandler.
Now, in Spring Boot world the way to configure it is a bit simpler than before.
There is a convenient class called RestTemplateBuilder. If you read the very first line of its java doc it says:
Builder that can be used to configure and create a RestTemplate.
Provides convenience methods to register converters, error handlers
and UriTemplateHandlers.
It actually has a method just for that:
new RestTemplateBuilder().errorHandler(new DefaultResponseErrorHandler()).build();
On top of that, Spring guys realized the drawbacks of a conventional RestTemplate long time ago, and how it can be especially painful in tests. They created a convenient class, TestRestTemplate, which serves as a wrapper around RestTemplate and set its errorHandler to an empty implementation:
private static class NoOpResponseErrorHandler extends
DefaultResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
}
}
You can create your own RestTemplate wrapper which does not throw exceptions, but returns a response with the received status code. (You could also return the body, but that would stop being type-safe, so in the code below the body remains simply null.)
/**
* A Rest Template that doesn't throw exceptions if a method returns something other than 2xx
*/
public class GracefulRestTemplate extends RestTemplate {
private final RestTemplate restTemplate;
public GracefulRestTemplate(RestTemplate restTemplate) {
super(restTemplate.getMessageConverters());
this.restTemplate = restTemplate;
}
#Override
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException {
return withExceptionHandling(() -> restTemplate.getForEntity(url, responseType));
}
#Override
public <T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException {
return withExceptionHandling(() -> restTemplate.postForEntity(url, request, responseType));
}
private <T> ResponseEntity<T> withExceptionHandling(Supplier<ResponseEntity<T>> action) {
try {
return action.get();
} catch (HttpClientErrorException ex) {
return new ResponseEntity<>(ex.getStatusCode());
}
}
}
Recently had a usecase for this. My solution:
public class MyErrorHandler implements ResponseErrorHandler {
#Override
public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException {
return hasError(clientHttpResponse.getStatusCode());
}
#Override
public void handleError(ClientHttpResponse clientHttpResponse) throws IOException {
HttpStatus statusCode = clientHttpResponse.getStatusCode();
MediaType contentType = clientHttpResponse
.getHeaders()
.getContentType();
Charset charset = contentType != null ? contentType.getCharset() : null;
byte[] body = FileCopyUtils.copyToByteArray(clientHttpResponse.getBody());
switch (statusCode.series()) {
case CLIENT_ERROR:
throw new HttpClientErrorException(statusCode, clientHttpResponse.getStatusText(), body, charset);
case SERVER_ERROR:
throw new HttpServerErrorException(statusCode, clientHttpResponse.getStatusText(), body, charset);
default:
throw new RestClientException("Unknown status code [" + statusCode + "]");
}
}
private boolean hasError(HttpStatus statusCode) {
return (statusCode.series() == HttpStatus.Series.CLIENT_ERROR ||
statusCode.series() == HttpStatus.Series.SERVER_ERROR);
}
There is no such class implementing ResponseErrorHandler in Spring framework, so I just declared a bean:
#Bean
public RestTemplate getRestTemplate() {
return new RestTemplateBuilder()
.errorHandler(new DefaultResponseErrorHandler() {
#Override
public void handleError(ClientHttpResponse response) throws IOException {
//do nothing
}
})
.build();
}
The best way to make a RestTemplate to work with 4XX/5XX errors without throwing exceptions I found is to create your own service, which uses RestTemplate :
public ResponseEntity<?> makeCall(CallData callData) {
logger.debug("[makeCall][url] " + callData.getUrl());
logger.debug("[makeCall][httpMethod] " + callData.getHttpMethod());
logger.debug("[makeCall][httpEntity] " + callData.getHttpEntity());
logger.debug("[makeCall][class] " + callData.getClazz());
logger.debug("[makeCall][params] " + callData.getQueryParams());
ResponseEntity<?> result;
try {
result = restTemplate.exchange(callData.getUrl(), callData.getHttpMethod(), callData.getHttpEntity(),
callData.getClazz(), callData.getQueryParams());
} catch (RestClientResponseException e) {
result = new ResponseEntity<String>(e.getResponseBodyAsString(), e.getResponseHeaders(), e.getRawStatusCode());
}
return result;
}
And in case of exception, simply catch it and create your own ResponseEntity.
This will allow you to work with the ResponseEntity object as excepted.

Resources