I am trying to move the assertThat method from Authentication class to the BDDStyledMethod class but the current code will generate the following error "'Creds(java.lang.String)' in 'steps.Authentication' cannot be applied to '()'"
How do i correct my code so that the assertThat method works in the BDDStyledMethod class ?
public class Authentication {
public static void Creds(String url){
RequestSpecification httpRequest=RestAssured.given()
.auth().oauth2(Authentication.login("user","password"));
Response response = httpRequest.get(url);
ResponseBody body=response.getBody();
body.prettyPrint();
System.out.println("The status received: " + response.statusLine());
assertThat("They are not the same",response.statusLine(),is("HTTP/1.1 200"));
}
}
public class BDDStyledMethod {
public static void GetActivityById(){
Authentication.Creds("www.randomurl.com");
assertThat("They are not the same",Authentication.Creds().response.statusLine(),is("HTTP/1.1 200"));
}
}
The problem is with the Creds method. It is not returning anything and the exception is raised in this line -> Authentication.Creds().response.statusLine()
We can return a string from Creds method and then try to apply assert() on the returned string in GetActivityById class.
public class Authentication {
public static String Creds(String url){
RequestSpecification httpRequest=RestAssured.given()
.auth().oauth2(Authentication.login("user","password"));
Response response = httpRequest.get(url);
ResponseBody body=response.getBody();
body.prettyPrint();
System.out.println("The status received: " + response.statusLine());
return response.statusLine().toString();
}
}
public class BDDStyledMethod {
public static void GetActivityById(){
String returned_str = Authentication.Creds("www.randomurl.com");
assertThat("They are not the same",returned_str,is("HTTP/1.1 200"));
}
}
Related
I am making a weather app by using the wunderground API. I am also using Retrofit2 and GSON library.
Here is the API URL format to get the JSON response:
http://api.wunderground.com/api/API_KEY/conditions/q/ISO_COUNTRY_CODE/CITY_NAME.json
I've declared an java API_Interface as follows:
public interface API_Interface {
#GET("/api/{apikey}/conditions/q/BD/{city}.json")
Call<CurrentObservation> getCurrentWeather(
#Path("apikey") String apikey,
#Path("city") String city);
}
And trying to pass the apikey and city from the MainActivity as follows:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
API_Interface weatherService = retrofit.create(API_Interface.class);
Call<CurrentObservation> call = weatherService.getCurrentWeather(Constants.API_KEY,"Dhaka");
call.enqueue(new Callback<CurrentObservation>() {
#Override
public void onResponse(Call<CurrentObservation> call, Response<CurrentObservation> response) {
textView.setText(response.body().toString());
Log.d("result",response.body().toString());
}
#Override
public void onFailure(Call<CurrentObservation> call, Throwable t) {
textView.setText("Something went wrong: " + t.getMessage());
Log.e("error",t.getMessage());
}
});
Here is the Constant class:
public class Constants {
public static final String BASE_URL="http://api.wunderground.com";
public static final String API_KEY="b5efba6dc63cc1b1";
}
and here is the POJO Model of CurrentObservation class: http://paste.ubuntu.com/22291964/
I've overriden a toString() method in the model.
There are some other POJO classes-
But this approach gives null response as following-
Weather Status: null
Pressure: null
Humidity: null
Temperature: null
Here is the actual JSON response from the API URL- http://paste.ubuntu.com/22292683/
How do I pass the parameters into #GET to get the correct response?
Your base URL should look like this:
http://blah.com/api/blah/
And your #GET method should have an URL like this
api/{apikey}/conditions/q/BD/{city}.json
EDIT: You might have onResponse called with an error body. Please adjust the following code for your use-case:
public static boolean handleError(Retrofit retrofit, Response<?> response) {
if(response != null && !response.isSuccessful() && response.errorBody() != null) {
Converter<ResponseBody, ErrorResponse> converter = retrofit.responseBodyConverter(ErrorResponse.class, new Annotation[0]);
try {
ErrorResponse errorResponse = converter.convert(response.errorBody());
// do something
} catch(IOException e) {
Log.e(TAG, "An error occurred", e);
}
return true;
}
return false;
}
You can do it like that:
#GET
Call<CurrentObservation> getCurrentWeather(#Url String url);
I have application with many rest services, most of them follows this pattern:
class RestService{
public Response execute1() {
try{
// doLogicThere...
return response;
} catch () {
// handle exception and build Response object..
return response;
}
}
public Response execute2() {
try{
// doLogicThere...
return response;
} catch() {
// handle exception and build Response object..
return response;
}
}
}
catch clause is the same for all methods so I want to have pattern like this below but with try/catch called from somewhere else. I want to do kind of wrapping these methods.
class RestService{
public Response execute1() {
// doLogicThere...
return response;
}
public Response execute2() {
// doLogicThere...
return response;
}
}
JAX-WS includes a mechanism for creating the proper response for each type of exception that your REST methods might produce.
For each exception type, create a class that implements ExceptionMapper<E> where E is the type of exception. You create your response in the toResponse method. You need to annotate your exception mapper with #Provider, in order to register it with the JAX-RS runtime.
#Provider
public class UserNotFoundMapper implements ExceptionMapper<UserNotFoundException> {
#Override
public Response toResponse(UserNotFoundException e) {
return Response.status(404).entity(e.getMessage()).type("text/plain").build();
}
}
You can create an interface with the method you need to execute. Then you can wrap that method in a try catch in a new method. This will avoid the use of many repeated try catch blocks.
You can do something like that:
public interface CallableClass {
public Response call();
}
...
class RestService {
private Response handleCall(CallableClass myClass) {
try {
return myClass.call();
} catch (Exception e) {
// Handle exception and return a particular response
...
}
}
public Response execute1() {
return handleCall(/* put anonymous class of type CallableClass here */);
}
public Response execute2() {
return handleCall(/* put anonymous class of type CallableClass here */);
}
}
If you are using java 8 you can replace the anonynous class with a more elegant lambda expression.
Here a simple example with lambdas
public Response executeLambda() {
return handleCall(() -> {
... // Your code here
return response;
});
}
You can use the "throws" keyword to indicate that a method throws certain exceptions. Then when you call that method you can simply wrap the call in a try/catch block.
See: https://docs.oracle.com/javase/tutorial/essential/exceptions/declaring.html
If you are building RESTFul Service using SPring MVC, you do have a better option of leveraging using following annotation "#ExceptionHandler(CustomExceptionForRestServices.class)". Where you can write your customException or have a comma seperated List of exception classes you expect your method to throw.
The #ExceptionHandler value can be set to an array of Exception types. If an exception is thrown matches one of the types in the list, then the method annotated with the matching #ExceptionHandler will be invoked. If the annotation value is not set then the exception types listed as method arguments are used.
Much like standard controller methods annotated with a #RequestMapping annotation, the method arguments and return values of #ExceptionHandler methods are very flexible.
I have created a little example in plain AspectJ, i.e. without any Spring. I even created a dummy Response class just so as to show the basic mechanics behind aspect-driven exception handling:
Dummy response class:
package de.scrum_master.app;
public class Response {
private int statusCode;
private String message;
public Response(int statusCode) {
this.statusCode = statusCode;
switch (statusCode) {
case 200:
message = "OK";
break;
case 202:
message = "Accepted";
break;
case 401:
message = "Unauthorized";
break;
default:
message = "Unknown status";
}
}
public int getStatusCode() {
return statusCode;
}
#Override
public String toString() {
return "Response(statusCode=" + statusCode + ", message=" + message + ")";
}
}
Driver application with two methods to be intercepted:
As you can see, both methods randomly throw exceptions which ought to be caught by an aspect later.
package de.scrum_master.app;
import java.util.Random;
public class RestService {
private static final Random RANDOM = new Random();
public Response someRequest() {
Response response = new Response(RANDOM.nextBoolean() ? 200 : 401);
if (response.getStatusCode() != 200)
throw new RuntimeException("request failed: " + response);
return response;
}
public Response anotherRequest(String argument) {
Response response = new Response(RANDOM.nextBoolean() ? 200 : 401);
if (response.getStatusCode() != 200)
throw new RuntimeException("request failed: " + response);
return response;
}
public static void main(String[] args) {
RestService restService = new RestService();
for (int i = 0; i < 3; i++) {
System.out.println(restService.someRequest());
System.out.println(restService.anotherRequest("foo"));
}
}
}
Exception handling aspect:
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.Response;
#Aspect
public class ResponseErrorHandler {
#Around("execution(de.scrum_master.app.Response *(..))")
public Response handleError(ProceedingJoinPoint thisJoinPoint) {
System.out.println("\n" + thisJoinPoint);
try {
return (Response) thisJoinPoint.proceed();
}
catch (Exception e) {
System.out.println(" Handling exception: " + e.getMessage());
return new Response(202);
}
}
}
Console log:
execution(Response de.scrum_master.app.RestService.someRequest())
Response(statusCode=200, message=OK)
execution(Response de.scrum_master.app.RestService.anotherRequest(String))
Response(statusCode=200, message=OK)
execution(Response de.scrum_master.app.RestService.someRequest())
Response(statusCode=200, message=OK)
execution(Response de.scrum_master.app.RestService.anotherRequest(String))
Handling exception: request failed: Response(statusCode=401, message=Unauthorized)
Response(statusCode=202, message=Accepted)
execution(Response de.scrum_master.app.RestService.someRequest())
Response(statusCode=200, message=OK)
execution(Response de.scrum_master.app.RestService.anotherRequest(String))
Handling exception: request failed: Response(statusCode=401, message=Unauthorized)
Response(statusCode=202, message=Accepted)
Feel free to ask follow-up questions if you do not understand the answer.
I have my service defined as:
#Path("/fileservice")
public class FileService {
#POST
#Path("/path")
#Consumes("application/xml")
public Response getFilePath(FileRequest fileRequest) {
System.out.println("....." + fileRequest.client);
(...)
}
My activator:
#ApplicationPath("/services")
public class JaxRsActivator extends Application{
}
And the XML file mapping is defined as:
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="fileDetails")
public class FileRequest {
#XmlElement public String path;
#XmlElement public String client;
And my client is:
public static void main(String args[]) throws Exception {
URI uri = new URI(SERVICE_URL);
Client client = ClientBuilder.newClient();
String xml = "<fileDetails> "
+ "<path>usr/test/a.pdf</path>"
+ "<client>abc</client>"
+"</fileDetails>" ;
Response response= client.target(uri).request().post(Entity.xml(xml));
System.out.println("Request posted :"+ response.getAllowedMethods());
System.out.println("Request posted, response status :"+ response.getStatus());
When I send request to the URL http://localhost:8080/xx/services/fileservice/path I'm getting response.getStatus() as 405.
What I'm doing wrong here?
I'm having problems implementing a custom class as response JSON in Retrofit2.
The call succeeds and when I log the body (using HttpLoggingInterceptor) I can see the JSON is fetched correctly.
The only problem is that it is not parsed into the custom class I created.
Here is my ServiceGenerator:
public class ServiceGenerator
{
//Base url for the API
public static final String API_BASE_URL = "http://base.url";
private static Retrofit.Builder GSONBuilder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <T> T createJSONService(Class<T> serviceClass)
{
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(logging);
Retrofit retrofit = GSONBuilder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}
Here is the ServiceInterface:
public interface ServiceInterface
{
class UserResponse
{
public int id;
public String email;
public String created_at;
#Override
public String toString()
{
return "UserResponse{" +
"id: " + id +
", email: " + email +
", created_at: " + created_at +
"}";
}
}
#GET("user/{userId}")
Call<UserResponse> currentUser(#Path("userId") int userId);
}
And this is where I actually call it:
public void getUser(int userId)
{
ServiceInterface clientCreate = ServiceGenerator.createJSONService(ServiceInterface.class);
Call<ServiceInterface.UserResponse> callCreate = clientCreate.currentUser(userId);
callCreate.enqueue(new Callback<ServiceInterface.UserResponse>()
{
#Override
public void onResponse(Call<ServiceInterface.UserResponse> call, Response<ServiceInterface.UserResponse> response)
{
ServiceInterface.UserResponse user = response.body();
if (user == null)
{
System.out.println("error");
}
else
{
System.out.println(user.toString());
//This line gets printed, but the class is empty
//What it should show: UserResponse{id: 5, email: "test#email.com", created_at: "2016-03-02"}
//What it actually shows: UserResponse{id: 0, email: null, created_at: null}
}
}
#Override
public void onFailure(Call<ServiceInterface.UserResponse> call, Throwable t)
{
System.out.println("Fail: " + t.getMessage());
}
});
}
I feel like I did everything right, is there any explanation why the GsonConverter does not convert the response to my custom class (UserResponse)?
To make myself even more clear, here is the actual JSON response (using Postman):
{"id": 5, "email": "test#email.com", "created_at": "2016-03-02"}
Thanks in advance!
Edit 1:
For anyone interested.
I have just figured out that if I use a String as a return type it actually writes all the data to the String.
So that means the fault lies with the conversion. I think that somewhere along the way I made a mistake with the GSONBuilder.
Hi guys I am trying to use scribe-java library to access the REST api via http.code looks
package org.scribe.examples;
import java.util.*;
import org.scribe.builder.*;
import org.scribe.builder.api.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
public class WooCommerceOauth1Example {
private static final String RESOURCE_URL = "http://WEBSITE.COM/wc-api/v1/orders";
public static void main(String[] args) {
OAuthService service = new ServiceBuilder().provider(OneLeggedApi10.class)
.apiKey("ck_SOME_NUMBER")
.apiSecret("cs_SOME_NUMBER")
.build();
// Now let's go and ask for a protected resource!
System.out.println("Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, RESOURCE_URL);
//Since it is a one legged protocol, access token is empty.Right?
service.signRequest(new Token("", ""), request);
Response response = request.send();
System.out.println("Got it! Lets see what we found...");
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
System.out.println();
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
}
}
Throws the following error
{"errors":[{"code":"woocommerce_api_authentication_error","message":"oauth_consumer_key parameter is missing"}]}
. Any Ideas why my code is throwing the above error? Note that I have checked the v1 endpoint with http and it returns sensible message back.so basically it is working.
Removing '&' + OAuthEncoder.encode(tokenSecret) from https://github.com/fernandezpablo85/scribe-java/blob/master/src/main/java/org/scribe/services/HMACSha1SignatureService.java#L32 and adding and changed signature type to QueryString and it works now.
I will propose a PR after cleaning.Thanks Pablo. Below is the full code
package org.scribe.builder.api;
import org.scribe.model.Token;
import org.scribe.model.Verb;
public class OneLeggedApi10 extends DefaultApi10a {
#Override
public String getAccessTokenEndpoint() {
return null;
}
#Override
public String getRequestTokenEndpoint() {
return null;
}
#Override
public String getAuthorizationUrl(Token requestToken) {
return null;
}
#Override
public Verb getAccessTokenVerb() {
return Verb.GET;
}
#Override
public Verb getRequestTokenVerb() {
return Verb.GET;
}
}
And the example class
package org.scribe.examples;
import org.scribe.builder.*;
import org.scribe.builder.api.*;
import org.scribe.model.*;
import org.scribe.oauth.*;
public class WooCommerceOauth1Example {
private static final String NETWORK_NAME = "Woocommerce";
private static final String RESOURCE_URL = "http://YOUR_DOMAIN/wc-api/v1/orders/count";
private static final String SCOPE = "*"; //all permissions
public static void main(String[] args) {
OAuthService service = new ServiceBuilder().provider(OneLeggedApi10.class)
.apiKey("API_KEY")
.apiSecret("SECRET_KEY")
.debugStream(System.out)
.signatureType(SignatureType.QueryString)
/*.scope(SCOPE).*/
.build();
System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
System.out.println();
// Now let's go and ask for a protected resource!
System.out.println("Now we're going to access a protected resource...");
OAuthRequest request = new OAuthRequest(Verb.GET, RESOURCE_URL);
service.signRequest(new Token("", ""), request);
Response response = request.send();
System.out.println("Got it! Lets see what we found...");
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
System.out.println();
System.out.println("Thats it man! Go and build something awesome with Scribe! :)");
}
}