1

In below two methods I would like to extract common methods, the problem I have is that aisleID in one of it is optional - is it any way to put optional argument in java method ?

private void putPageUnderAisleId(String aisleId) {
        given()
                .spec(prepareApplicationJsonHeaders())
                .header(HttpHeaders.AUTHORIZATION, verifiableToken(Roles.WRITE_MERCHANDISING))
                .body(readResource(NAMED_PAGE_CONTENT_FILE, String.format("%s.html", TEST_PAGE.value()), AISLE_TEST_LOCATION))
                .put(AISLE_HTML_URL, aisleId)
                .then()
                .statusCode(200)
                .body(not(isEmptyOrNullString()))
                .body(JSON_RESPONSE_MESSAGE, not(isEmptyOrNullString()));
    }

    private void putPageUnderRootAisleId() {
        given()
                .spec(prepareApplicationJsonHeaders())
                .header(HttpHeaders.AUTHORIZATION, verifiableToken(Roles.WRITE_MERCHANDISING))
                .body(readResource(NAMED_PAGE_CONTENT_FILE, String.format("%s.html", TEST_PAGE.value()), AISLE_TEST_LOCATION))
                .put(ROOT_AISLE_HTML_URL)
                .then()
                .statusCode(200)
                .body(not(isEmptyOrNullString()))
                .body(JSON_RESPONSE_MESSAGE, not(isEmptyOrNullString()));
    }
4
  • Extract a 3rd method to which you pass a lambda that does the put part. You invoke the lambda on the builder object at the appropriate step, then do the rest of the steps. Commented Nov 16, 2016 at 8:59
  • could you please provide ready example ... ? Commented Nov 16, 2016 at 9:00
  • void putPage(Consumer<Builder> c) { Builder b = given().spec(...)...; c.accept(b); b.then().statusCode(...)...; } Invoke with putPage(b -> b.put(AISLE_HTML_URL, aisleId); and putPage(b -> b.put(ROOT_AISLE_HTML_ID). Commented Nov 16, 2016 at 9:02
  • Possible duplicate of Java optional parameters Commented Nov 16, 2016 at 9:17

5 Answers 5

3

There may be a sleaker way of handling this with Java 8 lambda expressions, but you can expose putPageUnderAisleId(String aisleId), and when the input is null, then you would treat it as no parameter being passed. Something like this:

private void putPageUnderAisleId(String aisleId) {
    RequestSpecification instance = given()
            .spec(prepareApplicationJsonHeaders())
            .header(HttpHeaders.AUTHORIZATION, verifiableToken(Roles.WRITE_MERCHANDISING))
            .body(readResource(NAMED_PAGE_CONTENT_FILE, String.format("%s.html", TEST_PAGE.value()), AISLE_TEST_LOCATION));

    if (aisleId != null) {
        instance.put(AISLE_HTML_URL, aisleId)
    } else {
        instance.put(ROOT_AISLE_HTML_URL)
    }

    instance.then()
           .statusCode(200)
           .body(not(isEmptyOrNullString()))
           .body(JSON_RESPONSE_MESSAGE, not(isEmptyOrNullString()));
}
Sign up to request clarification or add additional context in comments.

6 Comments

At the very least you could first do given()...body(...), then the ifology just for the put() call, then continue on the common path with then()....
Yes, but what does put() actually return?
put has this line inside: return this;. It's not the this you have on the caller side :)
@TimBiegeleisen This is like a Builder return itself on each methods.
Take note that instance should be type RequestSpecification, this solution works fine and thanks for that :) !
|
2

Infortunately, you can't do this in Java.

You would have to declare both methods, but you can for example inprivate void putPageUnderRootAisleId() only call private void putPageUnderAisleId(null), and just handle the null case.

This discussion gives more information about your problem : Java optional parameters

5 Comments

You can do it using overloading. This will not be written like C++ or other langage using Default value but the usage is the same.
This is exactly what I meant, overloading and calling otherMethod(null)
I understood, even if you don't explain it with the correct term. But please, remove that first line or replace it by you can't do it in one method in Java ;)
The first question was : "is it possible in Java to have an optional/default parameter ?". In Java you can't. Please give a little more attention
This is just a matter of HOW to do it. Ow, and check Optional from Java 8 too !
1

Why not something like this?

private void putPageUnderRootAisleId() {
    return putPageUnderAisleId(null);
}

private void putPageUnderAisleId(String aisleId) {
    Object putKey = aisleId != null ? AISLE_HTML_URL : ROOT_AISLE_HTML_URL;
    given()
            .spec(prepareApplicationJsonHeaders())
            .header(HttpHeaders.AUTHORIZATION, verifiableToken(Roles.WRITE_MERCHANDISING))
            .body(readResource(NAMED_PAGE_CONTENT_FILE, String.format("%s.html", TEST_PAGE.value()), AISLE_TEST_LOCATION))
            .put(putKey, aisleId)
            .then()
            .statusCode(200)
            .body(not(isEmptyOrNullString()))
            .body(JSON_RESPONSE_MESSAGE, not(isEmptyOrNullString()));
}

The good part on this approach is that you only have to maintain one method. I defined the putKey as Object because I don't know wich library are you using. The only different part between both methods is the put() part. Just check the put method implementation. 99% sure the one with 1 argument calls the one with 2 providing as the second one a default value. If this default argument is null you are ready to go with mine. If it differs from null, then you only have to do an assignation like this to aisleId:

aisleId != null ? aisleId : %defaultValue;

being %defaultValue the default value the method put is using on the one argument implementation.

As pointed by @AxelH, if put receives varargs, the approach above is risky (and probably not correct), so in that case you should create an Object[] to provide these arguments:

private void putPageUnderRootAisleId() {
    return putPageUnderAisleId(null);
}

private void putPageUnderAisleId(String aisleId) {
    Object putKey = aisleId != null ? AISLE_HTML_URL : ROOT_AISLE_HTML_URL;
    Object[] putArgs = aisleId != null ? new Object[]{aisleId} : new Object[]{};

    given()
            .spec(prepareApplicationJsonHeaders())
            .header(HttpHeaders.AUTHORIZATION, verifiableToken(Roles.WRITE_MERCHANDISING))
            .body(readResource(NAMED_PAGE_CONTENT_FILE, String.format("%s.html", TEST_PAGE.value()), AISLE_TEST_LOCATION))
            .put(putKey, putArgs)
            .then()
            .statusCode(200)
            .body(not(isEmptyOrNullString()))
            .body(JSON_RESPONSE_MESSAGE, not(isEmptyOrNullString()));
}

4 Comments

Are you certain that you know the behavior or the put() method such that assuming a default value won't break something?
The structure is good but the implementation is risky, are you sure that passing a null value is the same as nothing passed ? if this is a varargs parameters, the number of parameter might be important, this need to be pointed ;)
You need Builder b = given().spec(...).header(...).body(...); b = aisleId != null ? b.put(AISLE_HTML_URL, aisleId) : b.put(AISLE_ROOT_HTML_URL); b.then().statusCode...
I'm not certain in this case, as I don't know which library is this. In most cases I've faced this problem one calls the other so the logic is not replicated all along the class (maybe it's not null and its "", but I have already explained that on my answer). Of course, this doesn't apply if we are talking of varargs, but in that case you can use an Object[] instead, and only add the aisleId in case it's not null
1

You can try with method overloading. Assuming that the put method accepts nulls aisleId, you can try the following.

 private void putPageUnderAisleId(String aisleId) {
          url=(aisleId!=null)?AISLE_HTML_URL:ROOT_AISLE_HTML_URL;

          given()
            .spec(prepareApplicationJsonHeaders())
            .header(HttpHeaders.AUTHORIZATION, verifiableToken(Roles.WRITE_MERCHANDISING))
            .body(readResource(NAMED_PAGE_CONTENT_FILE, String.format("%s.html", TEST_PAGE.value()), AISLE_TEST_LOCATION))
            .put(url, aisleId)
            .then()
            .statusCode(200)
            .body(not(isEmptyOrNullString()))
            .body(JSON_RESPONSE_MESSAGE, not(isEmptyOrNullString()));
}

private void putPageUnderRootAisleId() {

              putPageUnderAisleId(null);
}

There are several methods to handle optional parameters, see this answer.

Java optional parameters

4 Comments

Again, are you sure that you can pass a null value without risk ?
It depends by the API of course. Which API is it? Normally this method is enough safe, but it works as principle. Do you know which API is it ?
Normally this method is enough safe how could you assume that ? Since this is called put, I would guess this will insert values into a list, map, array... to generate some sort of parameter list. So maybe it will insert each parameters into a list. Meaning you are inserting a null here into the seconds parameter. Since the OP didn't insert null in his example, your assumption are incorrect until some proof ;)
I was meaning the method overloading. As I don't know the specific API, I made some basic assumption: - the put is not the HTML PUT method, but a method which puts an URL to call in the chain - the second argument is the ID to use for the possible object to retrieve.
0

Have you considered Java 8's new Optional container as a parameter?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.