Vavr: Another step towards functional programming in Java

Vavr(earlier known as SlangJava), is a functional library that helps to write code in Java using functional style as we write in Scala/JavaScript. It helps to reduce the amount of code and to increase robustness. Whenever we think about functional programming, Immutability is the first thing that comes to our mind. Vavr provides immutable collections and the functions that operate on these collections to fetch the desired results.

In Functional programming, Errors (or exceptions that are non-local goto statements) are not thrown instead they are also passed on to the very first method of the pipeline along with successful results. It helps to visualize programs as pipelines and a flow does not break in between. Vavr, as a functional library, helps to achieve all this.

Let’s understand with an example how an exception propagated back to the application’s entry point.

Repository method which throws an exception:

@Service
public class EmployeeRepository {

public String getEmployeeThrowsException2(int value) throws IOException, MalformedInputException {

System.out.println("get employee throws exception for employeeId");
if(value == 1)
throw new IOException("get employee throws exception for employeeId");
else
throw new MalformedInputException(value);
}
}

Service method which invokes the repository method:

@Service
public class EmployeeService {
public Try<String> readEmployee() {
//it takes only lambda function that's why vavr can be used with Java 8 or more
return Try.of(() -> employeeRepository.getEmployeeThrowsException2(10));
}
}

The controller method fetches the value from the result of the service method:

@RestController
@RequestMapping("/test")
public class EmployeeController {
@GetMapping("/read")
public String readEmployee() {

Try<String> employee = employeeService.readEmployee();

System.out.println(employee.isFailure()); //to check the readEmployee method response is having exception or not

System.out.println(employee.isSuccess()); //to check the readEmployee method response is having exception or not


//on success and failure, we can log or take other actions on Try
employee.onSuccess(System.out::println);
employee.onFailure(System.out::println);

System.out.println("printing andThen before");

//andThen has 2 implementations, so need to specify which implementation, we are intended to use
//Consumer or Runnable
//addFinally takes only runnable
employee.andThen((Consumer<String>) System.out::println).andFinally(()-> System.out.println("I am done with finally channel"));
    System.out.println("printing andThen after");

//in case of failure, failure can be recovered by this
employee = employee.recover(IOException.class, "ioException handling").recover(FilerException.class,
"filer exception handling");

System.out.println("printing andThen after recovering");

//andThen gets executed only in case of success
//andFinally get executed in both cases irrespective of the result
employee.andThen((Consumer<String>) System.out::println).andFinally(()-> System.out.println("I am done with finally channel after recovering"));

//now employee will have only success
//value can be fetched using get method
//return employee.get();

//suppose you dont want to recover, we can use getOrElse method to provide default value in case of failure

return employee.getOrElse("default value"); //here employee is already recovered, it will return recovered string only
}
}

Other APIs of Vavr:

  1. Future: A Future Future.of() is a computation result that becomes available at some point. All operations provided are non-blocking. The underlying ExecutorService is used to execute asynchronous handlers. It has 2 states: PENDING and COMPLETED
  2. Lazy: Lazy Lazy.of() is a monadic container type that represents a lazily evaluated value. Lazy is memoizing, as it evaluates only once and therefore is referentially transparent. Referential transparency is where a method definition can be replaced by its result.
  3. Stream: The io.vavr.collection.Stream implementation is a lazy linked list. Values are computed only when needed. Because of its laziness, most operations are performed in constant time.
  4. TryWithResources: The Try.withResources() can be used to declare the resources that must be closed once the program is finished. Any class that implements the AutoCloseable interface can be passed as a resource.

Conclusion

Vavr can be used to make our code more readable by following a functional programing style. Exceptions need not be handled in between the flow explicitly using try/catch blocks and can be read, recovered by the very first caller. It provides immutable collections by default. Memoization in Vavr makes its functions (working on its collections) more efficient. Refer to the official documentation of vavr at https://www.vavr.io/ to read more about it.

Thanks for reading!


Vavr: Another step towards functional programming in Java was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Shivanshu Goyal

Vavr(earlier known as SlangJava), is a functional library that helps to write code in Java using functional style as we write in Scala/JavaScript. It helps to reduce the amount of code and to increase robustness. Whenever we think about functional programming, Immutability is the first thing that comes to our mind. Vavr provides immutable collections and the functions that operate on these collections to fetch the desired results.

In Functional programming, Errors (or exceptions that are non-local goto statements) are not thrown instead they are also passed on to the very first method of the pipeline along with successful results. It helps to visualize programs as pipelines and a flow does not break in between. Vavr, as a functional library, helps to achieve all this.

Let’s understand with an example how an exception propagated back to the application’s entry point.

Repository method which throws an exception:

@Service
public class EmployeeRepository {

public String getEmployeeThrowsException2(int value) throws IOException, MalformedInputException {

System.out.println("get employee throws exception for employeeId");
if(value == 1)
throw new IOException("get employee throws exception for employeeId");
else
throw new MalformedInputException(value);
}
}

Service method which invokes the repository method:

@Service
public class EmployeeService {
public Try<String> readEmployee() {
//it takes only lambda function that's why vavr can be used with Java 8 or more
return Try.of(() -> employeeRepository.getEmployeeThrowsException2(10));
}
}

The controller method fetches the value from the result of the service method:

@RestController
@RequestMapping("/test")
public class EmployeeController {
@GetMapping("/read")
public String readEmployee() {

Try<String> employee = employeeService.readEmployee();

System.out.println(employee.isFailure()); //to check the readEmployee method response is having exception or not

System.out.println(employee.isSuccess()); //to check the readEmployee method response is having exception or not


//on success and failure, we can log or take other actions on Try
employee.onSuccess(System.out::println);
employee.onFailure(System.out::println);

System.out.println("printing andThen before");

//andThen has 2 implementations, so need to specify which implementation, we are intended to use
//Consumer or Runnable
//addFinally takes only runnable
employee.andThen((Consumer<String>) System.out::println).andFinally(()-> System.out.println("I am done with finally channel"));
    System.out.println("printing andThen after");

//in case of failure, failure can be recovered by this
employee = employee.recover(IOException.class, "ioException handling").recover(FilerException.class,
"filer exception handling");

System.out.println("printing andThen after recovering");

//andThen gets executed only in case of success
//andFinally get executed in both cases irrespective of the result
employee.andThen((Consumer<String>) System.out::println).andFinally(()-> System.out.println("I am done with finally channel after recovering"));

//now employee will have only success
//value can be fetched using get method
//return employee.get();

//suppose you dont want to recover, we can use getOrElse method to provide default value in case of failure

return employee.getOrElse("default value"); //here employee is already recovered, it will return recovered string only
}
}

Other APIs of Vavr:

  1. Future: A Future Future.of() is a computation result that becomes available at some point. All operations provided are non-blocking. The underlying ExecutorService is used to execute asynchronous handlers. It has 2 states: PENDING and COMPLETED
  2. Lazy: Lazy Lazy.of() is a monadic container type that represents a lazily evaluated value. Lazy is memoizing, as it evaluates only once and therefore is referentially transparent. Referential transparency is where a method definition can be replaced by its result.
  3. Stream: The io.vavr.collection.Stream implementation is a lazy linked list. Values are computed only when needed. Because of its laziness, most operations are performed in constant time.
  4. TryWithResources: The Try.withResources() can be used to declare the resources that must be closed once the program is finished. Any class that implements the AutoCloseable interface can be passed as a resource.

Conclusion

Vavr can be used to make our code more readable by following a functional programing style. Exceptions need not be handled in between the flow explicitly using try/catch blocks and can be read, recovered by the very first caller. It provides immutable collections by default. Memoization in Vavr makes its functions (working on its collections) more efficient. Refer to the official documentation of vavr at https://www.vavr.io/ to read more about it.

Thanks for reading!


Vavr: Another step towards functional programming in Java was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Shivanshu Goyal


Print Share Comment Cite Upload Translate Updates
APA

Shivanshu Goyal | Sciencx (2021-03-07T03:16:15+00:00) Vavr: Another step towards functional programming in Java. Retrieved from https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/

MLA
" » Vavr: Another step towards functional programming in Java." Shivanshu Goyal | Sciencx - Sunday March 7, 2021, https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/
HARVARD
Shivanshu Goyal | Sciencx Sunday March 7, 2021 » Vavr: Another step towards functional programming in Java., viewed ,<https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/>
VANCOUVER
Shivanshu Goyal | Sciencx - » Vavr: Another step towards functional programming in Java. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/
CHICAGO
" » Vavr: Another step towards functional programming in Java." Shivanshu Goyal | Sciencx - Accessed . https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/
IEEE
" » Vavr: Another step towards functional programming in Java." Shivanshu Goyal | Sciencx [Online]. Available: https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/. [Accessed: ]
rf:citation
» Vavr: Another step towards functional programming in Java | Shivanshu Goyal | Sciencx | https://www.scien.cx/2021/03/07/vavr-another-step-towards-functional-programming-in-java/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.