简体   繁体   中英

is create a class variable just to be used in Optional.ifPresentOrElse a practice to be avoid?

In few words my context is: call an API and if I find certain header variable I subString it to return a value. If not I must return the Response.status. I have successfully reached such requirement with this code:

...
import com.mashape.unirest.*
...
@Controller
public class MainController {
    private final String gmailKey = "XXX";

    private String stringRetorno = "0";

    @ResponseBody
    @GetMapping("/getsessionkey")
    public String getSessionKey() {

        try {

            HttpResponse<String> response = Unirest
                    .post("https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/pricing/v1.0")
                    .header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
                    .header("x-rapidapi-key", gmailKey).header("Content-Type", "application/x-www-form-urlencoded")

                    .body("inboundDate=2019-11-25&cabinClass=economy&children=0&infants=0&Country=BR&Currency=BRL&locale=pt-BR&originPlace=GRU-sky&destinationPlace=MCZ-sky&outboundDate=2019-11-19&adults=2")
                    .asString();

            Optional<String> optionalLocation = Optional.ofNullable(response.getHeaders().getFirst("Location"));

            optionalLocation.ifPresentOrElse(l -> stringRetorno = l.substring(l.lastIndexOf("/") + 1),
                    () -> stringRetorno = String.valueOf(response.getStatus()));

        } catch (Exception e) {
            e.printStackTrace();
        }

        return stringRetorno;

    }

My doubt relies in how properly I coded it. Instead of coding a chain of if&null I decided to use a more elegant and readble way with Optional. But I faced "Local variable stringRetorno defined in an enclosing scope must be final or effectively final" if I create stringRetorno inside of the method.

Searching around I found as solution create stringRetorno as class variable.

So my straigh question is: am I doing something to be avoid? Some questions that may not answer my question but be very usefull are:

  • should I prefer other Java HTTP Client than com.mashape.unirest which may already provide Optional so I would be able to write less verbose code? I don't want to compare libraries at all. My focus is coupling with the possibility to receive a response header missing a specific key (location). And if the lightweight unirest suggested by the API Provider forces me to workarounds maybe a suggestion of another library that provides Optional as answer should help me.

  • isn't overwhelming writing Optional inside of Try/Catch block?

*** Solution

thanks to answers provided

@ResponseBody
@GetMapping("/getsessionkey")
public String getSessionKey() {

    Optional<String> optionalLocation = null;
    HttpResponse<String> response = null;
    try {

        response = Unirest
                .post("https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/pricing/v1.0")
                .header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
                .header("x-rapidapi-key", gmailKey).header("Content-Type", "application/x-www-form-urlencoded")

                .body("inboundDate=2019-11-25&cabinClass=economy&children=0&infants=0&Country=BR&Currency=BRL&locale=pt-BR&originPlace=GRU-sky&destinationPlace=MCZ-sky&outboundDate=2019-11-19&adults=2")
                .asString();

        optionalLocation = Optional.ofNullable(response.getHeaders().getFirst("Location"));

    } catch (Exception e) {
        e.printStackTrace();
    }

    return optionalLocation.map(l -> l.substring(l.lastIndexOf("/") + 1))
            .orElse(String.valueOf(response.getStatus()));

}

ifPresentOrElse is probably not the method you want to use, but rather .orElse .

return optionalLocation.orElse(String.valueOf(response.getStatus()));

You would want to use ifPresentOrElse if there is some action you want to take, like logging, when the optional is empty.

am I doing something to be avoid?

Yes. It is poor form to pull the variable outside the only method to which it is relevant. Moreover, as a practical matter, it creates a thread-safety problem for you -- as currently written, a program that uses your class and allows two different threads to invoke MainController.getSessionKey() is for that reason likely to not be properly synchronized. The same would not be true if it were a local variable of the method.

You can use a variable that is local to the method if it is a mutable container for your string (an array, List , or AtomicReference , for example). Then the container can be final or effectively final, without preventing you from changing its contents.

But it would be cleaner to use a combination of map() and orElse() so that you don't need to set the string reference with a lambda in the first place:

stringRetorno = optionalLocation.map(l -> l.substring(l.lastIndexOf("/") + 1))
        .orElse(String.valueOf(response.getStatus()));
  • should I prefer other Java HTTP Client than com.mashape.unirest which may already provide Optional so I would be able to write less verbose code?

Perhaps I misunderstand, but the only code savings I see from that is removing the Optional.ofNullable() invocation (but keeping an equivalent of its argument). That's not much reduction in verbosity, nor much, if any, improvement in clarity. I wouldn't consider the potential to do that to be any reason to look for a different client.

(But if you do look for a different client, don't look here . Recommendations for libraries and other off-site resources are off-topic here.)

  • isn't overwhelming writing Optional inside of Try/Catch block?

Um, no? Maybe "overwhelming" isn't the term you're looking for, but even if you really mean "overkill" or "excessive" or similar, then still no. I'm not really even seeing why you suppose it might be so.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM