How to restrict allowable parameters and values when building a GET request? - java

I am trying to make a library that accesses an online RESTful API. The API has defined a list of implemented methods, and allowed parameters for each method and (in some cases) allowed values for given parameters. I was thinking I would like to ensure that (A) only implemented methods can be called; (B) only allowed parameters can be defined for a given method; and (C) where only certain values are allowed for a given parameter, only allow those values.
(A) is relatively easy just using an enum "Method":
public enum Method {
getObjectById,
getObjectBySearch,
...
}
for (B) I was thinking each instance of Method then needs to have it's own enum of allowed parameters and for (C) some parameters, an enum of allowed values, sort of like (I'm sorry if this makes anybody cringe):
NOTE: THE FOLLOWING CODE IS NOT VALID JAVA; IT IS ONLY HERE AS A CONCEPTUAL EXAMPLE.
public enum Method {
getObjectById () {
enum Parameter {
objectId;
},
getObjectBySearch () {
enum Parameter {
query,
queryType () {
enum Type { type1, type2 }
}
}
}
}
Obviously, local enumerations are not allowed in Java, so this can't be done; and I imagine there are more elegant ways to achieve my end goal, but I've been out of practice for over 5 years, so I'm struggling to find them.
Or perhaps I'm overthinking this and trying to achieve this kind of type safety in parameters and values of my request is really bad practice (again I'm not very experienced) - if this is the case, I would appreciate an explanation as to why it is bad practice.
Thanks,
- Igor

Why don't you just wrap every method call inside a service object which validates its arguments?
public class Service {
public SomeObject getObjectById(String objectId) {
if (isNotValidObjectId(objectId) {
throw new IllegalArgumentException("objectId is invalid");
}
// TODO call the appropriate method
}
public SomeObject getObjectBySearch(String query, QueryType queryType) {
if (isNotValidQuery(query) {
throw new IllegalArgumentException("query is invalid");
}
if (queryType == null) {
throw new IllegalArgumentException("queryType is mandatory");
}
// TODO call the appropriate method
}
}

Related

Purpose of Functional Interfaces in Java8

I've come across many questions in regards of Java8 in-built Functional Interfaces, including this, this, this and this. But all ask about "why only one method?" or "why do I get a compilation error if I do X with my functional interface" and alike. My question is: what is the existential purpose of these new Functional Interfaces, when I can use lambdas anyway in my own interfaces?
Consider the following example code from oracle documentation:
// Approach 6: print using a predicate
public static void printPersonsWithPredicate(List<Person> roster,
Predicate<Person> tester) {
for (Person p : roster) {
if (tester.test(p)) {
System.out.println(p);
}
}
}
OK, great, but this is achievable with their own example just above (an interface with a single method is nothing new):
// Approach 5:
public static void printPersons(<Person> roster,
CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
System.out.println(p);
}
}
}
interface CheckPerson {
boolean test(Person p);
}
I can pass a lambda to both methods.
1st approach saves me one custom interface. Is this it?
Or are these standard functional interfaces (Consumer, Supplier, Predicate, Function) are meant to serve as a template for code organization, readability, structure, [other]?
Obviously you can skip using these new interfaces and roll your own with better names. There are some considerations though:
You will not be able to use custom interface in some other JDK API unless your custom interface extends one of built-ins.
If you always roll with your own, at some point you will come across a case where you can't think of a good name. For example, I'd argue that CheckPerson isn't really a good name for its purpose, although that's subjective.
Most builtin interfaces also define some other API. For example, Predicate defines or(Predicate), and(Predicate) and negate().
Function defines andThen(Function) and compose(Function), etc.
It's not particularly exciting, until it is: using methods other than abstract ones on functions allows for easier composition, strategy selections and many more, such as (using style suggested in this article):
Before:
class PersonPredicate {
public Predicate<Person> isAdultMale() {
return p ->
p.getAge() > ADULT
&& p.getSex() == SexEnum.MALE;
}
}
Might just become this, which is more reusable in the end:
class PersonPredicate {
public Predicate<Person> isAdultMale() {
return isAdult().and(isMale());
}
publci Predicate<Person> isAdultFemale() {
return isAdult().and(isFemale());
}
public Predicate<Person> isAdult() {
return p -> p.getAge() > ADULT;
}
public Predicate<Person> isMale() {
return isSex(SexEnum.MALE);
}
public Predicate<Person> isFemale() {
return isSex(SexEnum.FEMALE);
}
public Predicate<Person> isSex(SexEnum sex) {
return p -> p.getSex() == sex;
}
}
Although you ask "Is that it?", it's very nice that we don't have to write a new interface ever time we want type for a lambda.
Ask yourself, if you're reading an API, which is easier for a programmer to use:
public void processUsers(UserProcessor userProcessor);
... or ...
public void processUsers(Consumer<User> userProcessor);
With the former, I have to go and take a look at UserProcessor to find out what one is, and how I could create one; I don't even know it could be implemented as a lambda until I go and find out. With the latter, I know immediately that I can type u -> System.out.println(u) and I'll be processing users by writing them to stdout.
Also the author of the library didn't need to bloat their library with Yet Another Type.
In addition, if I coerce a lambda to a Functional Type, I can use that type's composition methods, for example:
candidates.filter( personPredicates.IS_GRADUATE.negate());
That gives you Predicate methods and(), or(), negate(); Function methods compose(), andThen() -- which your custom type would not have unless you implemented them.
Java API provides many built-in Function Interfaces for java developers. and we can use the built-in Function Interfaces many times. but there two reasons to use a Customer Function Interface.
Use a Customer Function Interface to describe explicitly what's like.
let's say you having a class User with a name parameter on the constructor.when you use the built-in Function Interface to refer the constructor the code like below:
Function<String,User> userFactory=User::new;
if you want describe it clearly you can introduce your own Function Interface, e.g:UserFactory;
UserFactory userFactory=User::new;
another reason to use Custom Function Interface due to built-in Function Interface is confused in somewhere. when you see a parameter with type Function<String,User>,is it create a new user or query an user from database or remove the user by a string and return the user,...?if you use an exactly Function Interface you know what it doing,as an UserFactory is create an user from a string username.
Use a Customer Function Interface to processing checked Exception in java built-in Function Interface.
Due to the built-in Function Interface can't be throwing a checked Exception,the problem occurs when you processing something in lambda expression that may be throws a checked exception,but you don't want to use the try/catch to handle the checked Exception,which will be tends to many code difficult to read in lambda expression.then you can define your own Function Interface that throws any CheckedException and adapt it to the built-in Function Interface when using java API.the code like as below:
//if the bars function throws a checked Exception,you must catch the exception
Stream.of(foos).map(t->{
try{
return bars.apply(t);
}catch(ex){//handle exception}
});
you also can define your own Function Interface throws a checked Exception,then adapt it to built-in Function,let's say it is a Mapping interface,the code below:
interface Mapping<T,R> {
R apply(T value) throws Exception;
}
private Function<T,R> reportsErrorWhenMappingFailed(Mapping<T,R> mapping){
return (it)->{
try{
return mapping.apply(it);
}catch(ex){
handleException(ex);
return null;
}
};
}
Stream.of(foos).map(reportsErrorWhenMappingFailed(bars));

How to make sure specific parameters are passed to the method?

For example, there is a method public void set_gender(String gender) {}, make sure only "male" or "female" is passed to this method without using enumeration.
Also, how to meet this demand when the method declaration is public void set_gender(String... params) {}?
If there's no such way to realize this, how could I give a warning in IDE when someone is passing a string that this method could not understand, just like how it works in Android Studio when I'm passing a value that is not a flag that defined inside a certain Class.
These are 4 ways I could think of:
Use pre-defined method without parameter:
public void setMale() { /* TODO: Implement */ }
public void setFemale() { /* TODO: Implement */ }
Keep setGender() but use boolean values as its parameter instead of plain String. true means it's male, false female (or the other way around):
public void setGender(boolean male) { /* TODO: Implement */ }
Keep setGender() while using String as its parameter, and throw an IllegalArgumentException if the supplied parameter does not comply with the scope:
public void setGender(String gender) {
if (!"male".equalsIgnoreCase(gender) && !"female".equalsIgnoreCase(gender)) {
throw new IllegalArgumentException("Bad parameter");
}
/* TODO: Implement */
}
Just use enums which, frankly, was designed with this exact use cases in mind. Or IntDef if you're really that worried about performance.
Oh, and as an addition, this question you asked:
If there's no such way to realize this, how could I give a warning in
IDE when someone is passing a string that this method could not
understand, just like how it works in Android Studio when I'm passing
a value that is not a flag that defined inside a certain Class.
They achieve this by using IntDef. ;)
There is StringDef annotation for such cases. You can mark parameter with it and then check it in runtime to verify.

Conventionally, can a set() method return a value in Java?

I am learning how to write neat and organized code in Java. Can a set() method return a value or is there a more efficient/readable way of doing this?
public class Car {
private boolean mHasAxles;
private boolean mHasTires;
private Tires mTires;
public setAxels(boolean hasAxles) {
mHasAxels = hasAxles;
}
public boolean hasAxles() {
return mHasAxles;
}
public boolean setTires(Tires tires) {
if(hasAxles()){
mTires = tires;
mHasTires = true;
return true; // Returns true if it was able to set tires
}
return false; // Returns false because car did not have axels
// Therefore, tires could not be set
}
}
In this example, my question is specifically about the setTires() method. Should the class check whether the car has axles when setting the tires or should the logic be left to the class that uses Car? Should the setTires() method be called something else since it returns a value?
Strictly conventionally - no, a setter usually returns void.
Having said that, you are free to return boolean if you wish - conventions are often broken (even in the internal java api's) and the method signature, including it's return type, should inspire an interested developer to navigate into the code to see exactly why a boolean is returned.
To make it clearer, you might want to use a different method name, e.g. setTiresIfAble(Tires tires), or you could alternatively return void and throw an Exception as per below:
public void setTires(Tires tires){
if(!hasAxels()) {
throw new IllegalStateException("no axels!");
}
mTires = tires;
mHasTires = true;
}
Incidentally, mHasTires is redudant, you can always check if tires == null.
Lastly, you can avoid the m or Hungarian notation in java (as per convention), like this:
public setAxels(boolean hasAxels){
this.hasAxels = hasAxels;
}
A setSomething method shouldn't return anything
A trySetSomethingmust return a boolean which say if the set has been successful or not.
Why ? When you are writting some code, in Java, in C++, in any langage, you want that any reader of your code, which is probably a human being, can access to the knownledge of most of what a method do, just reading his name.
To complete this assertion, we can study the case that a set can fail. There are two possibilities to deal with failures, depending on the scope of the method :
if the scope of setSomething is protected, private or package, it means that you have control, as API developper, on the way it will be called. Possible failures can be managed with assertion, or with RuntimeException (as it's not necessay to declare a throws clause in the method signature).
if the scope of setSomething is public, it means that you don't have control, as API developper, on the way it will be call. You have to warn the users of your API that the setSomething isn't error-safe. You have to manage the possible failures with an Exception which has to be declared in a throw clause.
You "can" return a value, but by convention setters don't return a value. As setters generally are used in a manner where one doesn't even reference a return value it is quite easy for any caller of your class to ignore that you are returning a value. Nothing stops the called from doing:
myCar.setTires(aTire);
...and ignoring you even return a Boolean, because that is the normal way setters are called and used. This defeats the purpose of your returning a value if the caller can just ignore it and the code appears correct.
My first inclination is to say throw an java.lang.IllegalArgumentException rather than return false.

Design for request bucket information on client

I'm trying to find the best way to design the client side storage of "buckets". To explain, the server sends down info like:
{
'buckets': {
'some_cool_bucket' : 'val1',
'another_bucket' : 'name'
}
}
Where the values can be
'some_cool_bucket' : 'val1' | 'val2' | 'val3'
'another_bucket' : 'name' | 'cool' | 'other'
basically all these buckets are enums with all the possible values known to both client and server, though there aren't common constraints, like buckets can have any number of possible values (no size limit), and any naming scheme.
I'm struggling against Java to find a design I am happy with. Forget about parsing JSON, blah blah blah, from a design point of view I want to know I can store this data that meets these requirements:
Each bucket needs to be able to store a default value in case server doesn't send one down
bucket.isBucket(...) should be type safe, ie, if we use an enum here, you shouldn't be able to pass in a bucket that doesn't belong without getting an error.
Easy, simple access. Buckets.some_cool_bucket.is(val1) would be ideal.
Minimal boiler plate in adding a new bucket
Non confusing design
Ignoring these requirements, we could implement this as follows:
enum Bucket {
some_cool_bucket('val1'),
another_bucket('name');
Bucket(String default) {
[...]
}
// Assume this retrieves the stored value sent down from the server.
String getVal() {
[...]
}
boolean is(String val) {
return getVal().equals(val);
}
}
With usage Bucket.some_cool_bucket.is('val1'). Naturally, we would want to extend this by changing the type signature of is() to accept some val enum defined by some_cool_bucket. Since the values a bucket can take are not uniform, we'd have to define this inside the some_cool_bucket enum. But you can't have enums inside enums in Java.
Ok, reset. Let's try this again:
public abstract class BaseBucket<E extends Enum<E>> {
private final Class<E> mClazz;
private final E mDefaultBucket;
public BaseBucket(Class<E> clazz, E defaultBucket) {
mClazz = clazz;
mDefaultBucket = defaultBucket;
}
// Assume this retrieves the stored value sent down from the server, uses
// getName() to match with the data.
protected E getVal() {
[...]
}
protected abstract String getName();
public boolean is(E test) {
return getVal() == test;
}
}
public class SomeCoolBucket extends BaseBucket<Val> {
public SomeCoolBucket() {
super(Val.class, Val.val1);
}
#Override
public String getName() {
return "some_cool_bucket";
}
public enum Val {
val1, val2, val3;
}
}
public Buckets {
public static final SomeCoolBucket some_cool_bucket = new SomeCoolBucket();
}
Ok, this works! Great. It meets all the functional requirements, but it's cumbersome and I hate having to create a new class for each bucket. I find it hard to justify all of the code, though I believe the requirements are sound.
Does anyone have a better solution for this?
What you can do in this case is have the abstract BaseBucket class, but remove the generics bits. The base class can have an instance variable of the Enum type. To do this without generics you can use the Strategy design pattern. Using this you can make all your Enum types implement a common interface. For the sake of an example you can call this IBucketEnum. Therefore, your BaseBucket class will have an instance variable of the IBucketEnum type and will look something like this:
public abstract class BaseBucket{
private IBucketEnum enum;
//other instance vars
public String getName(){
enum.getName();
}
}
From there you can have different versions of the BaseBucket and they will have the implementations and instance variables inherited from the base one, but can be extended with additional things that you need.
Hope this helps.

How to name class name according to Java Generics type return?

< T > T foo(P p) {
...
}
I'll get different types of return from foo according to the parameter I inserted, which means T changes according to p.
Then I try to call this function and use its return result.
Class x = foo(p);
What should I write in substitute of Class here?
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
Let me give the exact sample here.
public <T> List<T> getProperty(Property property) {
switch(property) {
case NAME: List<Name> names = new ArrayList<Name>();
names.add(this.name); return (List<T>) names;
case PHONE: return (List<T>) this.phones;
case EMAIL: return (List<T>) this.emails;
case ADDRESS: return (List<T>) this.addresses;
case NOTE: List<Note> notes = new ArrayList<Note>();
notes.add(this.note); return (List<T>) this.note;
default: return null;
}
}
public enum Property {
NAME, PHONE, EMAIL, ADDRESS, NOTE
}
public List<Entry> search(Property property, String s) {
if(this.isEmpty()) {
return null;
}
List<Entry> result = new ArrayList<Entry>();
for(Entry e : entries) {
if(e.getProperty(property) != null) {
for( **Object** p : e.getProperty(property)) { //What should I write instead of Object
if(p != null) {
if(p.containString(s)) { //there'll be errors if use Object. Need to know p's class.
result.add(e);
}
}
}
}
}
return this.nonDuplicatedResult(result);
}
I'm really not sure what you're asking. You haven't explained your use cases at all and haven't given us much code to look at. It's difficult to provide useful feedback from within the fog of obfuscation.
Generally speaking, if you want a method that returns a different object depending on the value of a supplied argument, then what you're probably talking about is a static factory method which can return any object that is a subtype of the method's return type. It is convenient to make such objects a part of an interface-based type system (eg. the static factories for the EnumSet class).
The use of an interface-based type system is actually necessary if you wish to return an enum, because enums cannot be part of a class hierarchy, but they can implement an interface that forms an interface-based type system.
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
No it isn't. The return type is P. You're over-thinking this. The 'enum' case isn't a job for Generics at all.
Assuming you have an finite number of return types, you could just check through each one using instanceof to see if the returned value is of a certain type. So in this case Object would substitute class, then you could later cast it.
What is happening is basically with that method definition, what you are saying to the compiler is that your method will return whatever the parameter assignment declares itself to be. You can do that, but how your method is implemented will boil down to a compiler warning, as you can't actually ensure that you are generating the appropriate type - since you don't know it, it is never passed to the method, and erased at compile time.
More typically what you would do is:
<T extends P> T foo(T p) {
...
}
Now you get an object of the right type as a parameter, so you have some idea of what to return. That concept has little utility with enums, though.
Here is a real world example of where you could use the method definition you posed in your question:
public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
}
Of course such a method generates a compiler warning. Now, what you are saying here is that the caller will define a variable, and will be sure to pass in at least one interface of the type they define. If they don't, they will end up with a ClassCastException at runtime, but you avoid calling code that knows what it is doing from explicitly casting.
It is debatable if that is a good idea.
So the short answer is that you can define the Class to be whatever you want - the compiler will accept anything - but if the method doesn't return the correct type, you will get an exception at runtime, so it is all about how you implement the method. Rarely can a method be smart enough to return the right thing without the correct type as a parameter. And if you can't pass in an appropriate parameter declared with the generic type to the method, you will have to deal with a compiler warning in order to return anything (other than null).

Categories

Resources