I have a class API, where you set and get the info you need to later be used on a API call
I want to make it easier to the next person who's gonna use this.
So instead of doing this:
api.addURL("urltorequesttoken");
api.addHeader("client_id","sdfsfsdfsd")
.addHeader("client_secret","sdfsdfsfsfd")
.addHeader("grant_type","client_credentials")
.addHeader("scope","READ");
api.addBody("bodyToSend")
I want to do this:
String URL = "";
URL = "put your URL here";
So I pass the URL and other variables as a parameter to another method where I will be doing what I did in the first block of code,so they don't need to know about the API class and its methods, but I dont know how to handle the hashmap, how can I do that user friendly? and then pass that as a parameter, also, what type of parameters should the methods receiving this info have? (Map<String key, String value>) or (String key, String value)?
EDIT(ADD):
So there's a class that a DEV is going to create, let's call it CreateToken
, so that class currently has:
api.addURL("urltorequesttoken");
api.addHeader("client_id","sdfsfsdfsd")
.addHeader("client_secret","sdfsdfsfsfd")
.addHeader("grant_type","client_credentials")
.addHeader("scope","READ");
api.addBody("bodyToSend")
There's another class called BASE, where Im doing the core services, in order for this to be easier for the person when they create their class, I dont want to have that block of code on their class, but instead, on mine, so in their class all they have to do is set the URL, headers and body(for POST method), so instead of this:
api.addURL("urltorequesttoken");
they will do:
URL = "urltorequesttoken";
and there's a method on their class to send me this or for me to get it i,e.
fillAPICallInfo(URL, headers, body);
I will receive that on the BASE class, but I dont know how to handle the Map variables, don't know how to make it easy for the DEV so they just put the key and value, and how do I receive that on my class (as a Map or as Strings)?
So you simply can pass a Map<String, String> as parameter:
public void fillAPICallInfo(String url, Map<String, String> headers, String body) {
// Assuming there is an instance of class DEV named api available
api.addURL(url);
headers.forEach((h, v) -> api.addHeader(h, v));
api.addBody(body);
}
Related
I have a resource class and within it a #GET that takes one query param called operation (this should be static) and then I want to take a variable number of other query params that can be named anything.
My first thought was to do something like this:
public Response get(
#QueryParam("operation") String operation,
#QueryParam("list") final List<String> list) {
//do stuff
}
The problem here is that I would have to make a request like:
...?operation=logging&list=ABC&list=XYZ
While what I want is to be able to have something like this:
...?operation=logging&anything=ABC&something_else=XYZ
Is there a way to make the list query param #QueryParam(//anything)?
In doing some information gathering I ran across this sort of approach:
#GET
public void gettest(#Context UriInfo ui) {
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
String operation = queryParams.getFirst("operation");
for (String theKey : queryParams.keySet()) {
System.out.println(queryParams.getFirst(theKey));
//do stuff with each other query param
}
}
Is multivaluedmap the way to go for this situation -- Or is there a way to use a variable query param name? Or a better approach? Thanks.
Edit/Update:
This is using javax.ws.rs
The use case is: this application being used as a tool for mocking responses (used for testing purposes in other applications). The mock responses are retrieved from a DB by looking up the 'operation' and then some sort of 'id'. The actual id used could be any of the "list" query params given. The reason for this is to give flexibility in different applications to use this mock service -- the urls in applications may be constructed many different ways and this makes if so one doesn't have to change around their code to be able to use the mock service.
As in this question, use a map:
#RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
#RequestParam Map<String,String> allRequestParams, ModelMap model) {
return "viewName";
}
I have a use case where I am creating multiple AWS resources, for example S3 buckets, SNS topics etc in a cloudformation stack. All of these are bare minimalistic resources i.e the S3 bucket would not have any objects in it.
I have a workflow set up where my code will pick up a random resourceType and then create the resource. Now, I am trying to build a generic class/method which would delete these created resources.
I store the resources as json fields which give me the details about the resourceType
{
"AWSService": "S3",
"AWSResourceType": "Bucket",
"ResourceAttributes" : {
"BucketName": "MyBucket"
}
}
For the cleanup, I was thinking that I have a map with key as the AWSService and the value to be a runnable which would call the appropriate serviceType to delete the resource.
But, runnables cannot take in parameters, and therefore I cannot pass in the resourceName/Arn to be deleted so that the API knows which resource to delete.
Is there a way I can store this information as a map and still pass in parameters to the method being executed?
Not sure I fully understand all of the implications of what you are doing without seeing some code, but I think this might get you going in the right direction.
You can implement the Runnable interface in a new generic class: http://leo.ugr.es/elvira/devel/Tutorial/Java/essential/threads/clock.html
So what you could do is create a generic class that implements the runnable interface, and has either a constructor that can take the variables you need, or getters/setters, etc.
Something along the lines of:
public class ResourceCleanup implements Runnable {
private String arn;
#Override
public void run() {
// do the cleanup with the arn
}
public ResourceCleanup(String arn) {
this.arn = arn;
}
// etc.
}
Or you could pass in the map instead of the String, use Java Generics, etc. as necessary. Hope this helps!
I overwrote the public Action onRequest(final Http.Request request, Method method) method to check that the mandatory http headers are passed in and valid, i.e.: I extract the apiKey (and other things) and make sure that these are valid (that there's data associated with the apiKey). Then I call return super.onRequest(request, method); and I end up in my controller where I once again have to extract the apiKey and get the associated data from the DB.
Is there a way to pass in the data to my controller's method (for instance: public static Result addUser() ).
Thank you.
I know this question is for Java, but I work with Play in Scala, and this question is more related to Play then it is to Java
In Scala I am able to extend WrappedRequest to make my own custom request type, that has instance variables I want to access in my controller:
// Scala code
case class MyRequest[A](request: Request[A]) extends WrappedRequest(request) {
// This is a public instance variable
val apiKey = request.headers.get("Authorization)
}
Then later on in my controller I can access the action object which now has the type of MyRequest:
// Scala code
def foobar(action: MyRequest[AnyContent]) = Action {
// Do something with the api key
val apiKey = action.apiKey
// Send back a response
Ok("foobar")
}
In Java it looks like you can do something similar using a Wrapped Context
Using the Retrofit REST Client library from Square, is there anyway of providing default/constant values for POST/PUT fields in a call.
I know about including constant query parameters by simply including them in the path, but this work for Body parameters.
I have an API that looks similar to:
POST /api/create
type=constanta&value={value}
POST /api/create
type=constantb&value={value}&otherValue={otherValue}
where the second variant requires an additional argument to be supplied. Rather than having a single java method that took all three arguments, I was hoping to be able to elide the constants from the method call, something like:
create(String value);
create(String value, String otherValue);
and have retrofit inject the type argument constant.
Given that adding #FormUrlEncoded can be added to modify how the body is encoded, if it's not natively supported by Retrofit, is there anyway of adding my own annotation and injecting such default values? ( It doesn't appear that RequestInterceptor allows one to modify the body.. ).
Maybe one option would be to send an object, which encapsulates all your values, instead of all string values separately? The object would implement your default values.
For example, you could create a class:
public class CreateObject {
private String type = "constant";
private String value;
private String otherValue;
public CreateObject(String value, String otherValue) {
this.value = value;
this.otherValue = otherValue;
}
}
Your class handles your constant. You could just set it to a default value "constant", like I did above, or set it on the fly in the constructor.
Now all you've to do is to create the object with the values and make the request with Retrofit. Instead of using the string values directly, just pass the object. Your interface could look like this:
public interface CreateService {
#POST("/api/create")
void create(#Body CreateObject create, Callback<CreateObject> cb);
}
The request implementation like this:
CreateObject create = new CreateObject("value", "otherValue");
createService.create(create, new Callback<CreateObject)() {…});
This should include all three of your values in the request body, if they are set. If a value is null, it won't be included in the request body. Based on your two examples above, you would now only need one interface method. Which values are sent is based on the createObject you pass on. For example, if you set otherValue as null, it won't be part of the request body.
My examples were modified from: https://futurestud.io/blog/retrofit-send-objects-in-request-body/
Is it possible for you to use Guava or Java 8 Optional as second argument in method? Then if that argument will be absent you can just ignore it
I'm working on API which should provide simple access to number of remote web-service based resources.
Some of these remote resources requires special parameters to be passed before interaction. For example, one of them requires pair of developer's keys to be passed, another requires pair of keys and unique identifier. Third one doesn't require these parameters at all. I'm working with 3 services now but their number can be enlarged.
For each web-service I have correspondent implementation of my API. The problem is that I don't know how to introduce to my API possibility to pass unknown number of Strings with unknown meanings.
Some of my suggestions:
1.
ServiceFactory.createService (ServiceEnum type, Properties keys);
2.
ServiceFactory.createService (ServiceEnum type, ServiceParams params);
Where ServiceParams is a marker-interface. In this case I'll have some helper-class like this:
public class ServiceHelper {
public static ServiceParams createFirstServiceParams (String secretKey, String publicKey);
public static ServiceParams createSecondServiceParams (String secretKey, String publicKey, String uid);
public static ServiceParams createThirdServiceParams ();
}
Pros: meaningful parameter names for each service.
Cons: if I provide support for fourth service then user will have to update factories module. In the first case user will only have to download new module.
3.
ServiceFactory.createService (ServiceEnum type, String ... params);
Pros: the most easy to use. User don't need to do any additional actions (like creating properties of ServiceParams).
Cons: the most unobvious way. User should know which set of params corresponds to the service he wants to create.
4-6:
the same variants but params are being passed not to factory method but to Service instance (in its init() method for example).
Pros: user can change keys for his service if he need without necessary to create new instance of the same service.
Cons: more complicated way, profit is questionable.
Which variant do you prefer? Why? Your variants are welcome.
You could have two factory methods, one where you pass a Map containing parameters, and the other without parameters:
ServiceFactory.createService(ServiceEnum type);
ServiceFactory.createService(ServiceEnum type, Map<String,?> params);
In this case, it's the responsibility of the caller to get the parameters right, but it gives you maximal flexibility.
I would probably go with option 1 and replace Properties with Map, which is what Properties uses for its underlying implementation.