Using Scala's Either, Right and Left from Java - java

How might a Java program wrap a value into a scala.Either? For example, how would the following Scala code be written in Java?
Right("asdf")
Left(new Exception())
The following fails with "cannot find symbol method apply(java.lang.String)"
Right.apply("asdf");
The following fails with "cannot find symbol method apply(java.lang.Exception)"
Left.apply(new Exception());

If I understand the question correctly, assume you have the following Scala method:
def foo(stringOrDate: Either[String, Date]) {
//...
}
you can call it from Java code by single creating Either subclasses instances:
scalaObject.foo(new Left<String, Date>("abc"));
scalaObject.foo(new Right<String, Date>(new Date()));
If you want to pass functions from Java code, you have to implement Function* trait depending on the function arity:
def foo(stringOrStringFun: Either[String, () => String]) {
//...
}
In Java:
scalaObject.foo(new Left<String, scala.Function0<String>>("abc"));
scalaObject.foo(new Right<String, scala.Function0<String>>(
new scala.Function0<String>() {
#Override
public String apply() {
throw new RuntimeException();
}
}));
Of course in Scala it is much simpler as it supports lambdas on the syntax level:
foo(Left("abc"))
foo(Right(throw new RuntimeException()))

Related

scala compiling error: Cannot resolve overloaded method 'withTransaction'

I'm new to Scala, and I can't figure out how to solve a compiling error for method withTransaction :
Cannot resolve overloaded method 'withTransaction'
object Global {
def goBootstrap(app: Application) {
Logger.info(" **** start *****")
onGet();
}
def onGet() {
import play.db.jpa.JPA
Logger.info("Cnnection start");
JPA.withTransaction(JPA.em =>
{
val resultsList = JPA.em.createNamedQuery("findCity").setParameter("name", "Boston").getResultList
}
);
}
}
This code snippet is located in a Global.scala file in Play project (version 2.3.X). JPA came from import play.db.jpa.JPA
How can I solve this compiling error?
The error is telling you that there is no method on JPA whose signature matches the parameters you're passing. You are calling JPA.withTransaction( () => Unit).
Looking at the source there are three methods withTransaction with Unit return types:
void withTransaction(Consumer<EntityManager> block);
void withTransaction(String name, Consumer<EntityManager> block);
void withTransaction(String name, boolean readOnly, Consumer<EntityManager> block);
I'm going to assume that you're trying to use the first of those methods. Looking at the docs for Consumer it requires a single argument.
In short, you need to provide an input to your block, something like:
JPA.withTransaction(JPA.em => {
val resultsList = JPA.em.createNamedQuery("findCity").setParameter("name", name).getResultList
});
The problem is that you can't directly instantiate a JPA connection through scala. Also because the play 2.3 framework does not support this feature: https://www.playframework.com/documentation/2.3.x/ScalaHome

Java/Kotlin callback syntax - do I really need 2 callback definitions after conversion to Kotlin?

I have a problem that has been challenging me for a few days with no resolution (more directly, no resolution I feel is correct). The issue is around callbacks, Java implementation vs Kotlin implementation
I have this Java method:
public void setOnSelectionChange(MapControlUpdate mapMenuControl) {
this.mapControlUpdate = mapMenuControl;
}
private MapControlUpdate mapControlUpdate;
public interface MapControlUpdate {
void onSelectionChange(MAP_TYPE mapType);
}
Using the above implementation I have what I want (below) in both Java and Kotlin.
Java (before):
widgetMapType.setOnSelectionChange(mapType -> {
Toast.makeText(getContext(), "clicked: " + mapType, Toast.LENGTH_LONG).show();
});
Kotlin (before):
widgetMapType.setOnSelectionChange {
Toast.makeText(context, "clicked: $it", Toast.LENGTH_LONG).show()
}
The new Kotlin code, after conversion is:
fun setOnSelectionChange(mapMenuControl: MapControlUpdate?) {
mapControlUpdate = mapMenuControl
}
private var mapControlUpdate: MapControlUpdate? = null
After the conversion to Kotlin the Java usage remains unchanged but I need to change the Kotlin code as follows or I get a syntax error:
Kotlin (after):
widgetMapType.setMapMenuControl(object: WidgetMapType.MapControlUpdate {
override fun onSelectionChange(mapType: WidgetMapType.MAP_TYPE?) {
Toast.makeText(context, "clicked: $mapType", Toast.LENGTH_LONG).show()
}
})
In order to get back to where I'd like to be I found that the only solution appear to be to implement 2 callbacks; 1 to allow Java to work with the original syntax and another to allow Kotlin syntax to remain the same.
This is the code I'm using (it works):
var onSelectionChange: MapControlUpdate? = null
private var onSelectionChangeListener: ((MapDisplayTypes?) -> Unit)? = null
fun setOnSelectionChange(listener: (MapDisplayTypes?) -> Unit){
onSelectionChangeListener = listener
}
and I fire both callbacks as appropriate
onSelectionChange?.onSelectionChange(it) // Java
onSelectionChangeListener?.invoke(it) // Kotlin
I really cannot believe that there isn't a more correct method but my searches (here and on the web) have returns tons of examples for Kotlin and Java but they all align with my above examples based on the code (also shown above). I suspect there maybe an annotation or something that I'm missing so finding no other solution I'm turning to the community here.
Thank you ahead of time!!
I suspect that you will need to keep just your interface MapControlUpdate definition in Java.
Instead of two callbacks you would keep just one callback and convert as appropriate:
var onSelectionChange: MapControlUpdate? = null
fun setOnSelectionChange(listener: (WidgetMapType.MAP_TYPE?) -> Unit){
onSelectionChangeListener = object : MapControlUpdate {
override fun onSelectionChange(mapType: WidgetMapType.MAP_TYPE?) {
listener(mapType)
}
}
}
Or write a helper function if MapControlUpdate is used more than once.
But the real solution is, as karmakaze says: keep the interface in Java until Kotlin 1.4 and then declare it as fun interface.

How to use Java 8 optional API for method calls that return void

I am a newbie to Java 8 APIs. I have this piece of code, which needs to be optimized using Java Optional.
if (Objects.nonNull(someDao.getById(id))) {
someDao.delete(id);
} else {
throw new RuntimeException();
}
I tried using Optional.ofNullable to optimize this piece of code.
Optional.ofNullable(someDao.getById(id))
.ifPresent(deleteObject)
.orElseThrow(() -> new RuntimeException("some error message"));
private Consumer<SomeObject> deleteObject = someObj-> {
someDao.delete(someObj.getId());
};
I am getting an error saying "can't invoke orElseThrow on primitive type void"
How can this be optimized to handle both data persistence and exception handling without using if-else blocks using Optional?
You need to do this in two separate calls:
Optional<SomeType> opt = Optional.ofNullable(someDao.getById(id));
opt.ifPresent(deleteObject);
opt.orElseThrow(() -> new RuntimeException("some error message"));
I think the if-statement you have is clear and don't see why you'd want to turn it in an Optional chain.
That being said, I also didn't manage to get it all done in one chain:
SomeObject someObj = Optional.ofNullable(someDao.getById(id))
.orElseThrow(() -> new RuntimeException("some error message"));
someDao.delete(someObj.getId());
.orElseThrow returns the value contained in the Optional if it is not null. So you can store it in a SomeObject and then delete it.

java try-with-resource not working with scala

In Scala application, am trying to read lines from a file using java nio try-with-resource construct.
Scala version 2.11.8
Java version 1.8
try(Stream<String> stream = Files.lines(Paths.get("somefile.txt"))){
stream.forEach(System.out::println); // will do business process here
}catch (IOException e) {
e.printStackTrace(); // will handle failure case here
}
But the compiler throws error like
◾not found: value stream
◾A try without a catch or finally is equivalent to putting its body in a block; no exceptions are handled.
Not sure what is the problem. Am new to using Java NIO, so any help is much appreciated.
If your are on Scala 2.13 then you should use the Using object:
import scala.util.Using
val a: Try[Int] = Using(new FileInputStream("/tmp/someFile")) { fileInputStream =>
// Do what you need in fith you fileInputStream here.
}
It takes two functions. The first one is a function that can create or provide the closable resource, and the second function is the one that takes the closable resource as a parameter, and can use it for something. Using will then in simple terms do the following for you:
Call the first function to create the closable resource.
Call the second function, and provide the resource as a parameter.
Hold on to the returned value of the second function.
Call close on the resource.
Return the value (or exception) it got from the second function wrapped in a Try.
Using can be used on many other things than Classes that implements AutoCloseable, you just have to provide an implicit value, telling Using how to close your specific resource.
In older versions of scala, there is no directly support for javas try-with-resources construct, but your can pretty easy build your own support, by applying the loan pattern. The following is a simple but not optimal example, that is easy to understand. A more correct solution is given later in this answer:
import java.lang.AutoCloseable
def autoClose[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): B = {
try {
fun(closeable)
} finally {
closeable.close()
}
}
This defines a reusable method, that works pretty much like a try-with-resource construct in java. It works by taken two parameter. First is takes the a subclass of Autoclosable instance, and second it takes a function that takes the same Autoclosable type as a paremeter. The return type of the function parameter, is used as return type of the method. The method then executes the function inside a try, and close the autocloseble in its finally block.
You can use it like this (here used to get the result of findAny() on the stream.
val result: Optional[String] = autoClose(Files.lines(Paths.get("somefile.txt"))) { stream ⇒
stream.findAny()
}
In case your want to do catch exceptions, you have 2 choices.
Add a try/catch block around the stream.findAny() call.
Or add a catch block to the try block in the autoClose method. Note that this should only be done, if the logic inside the catch block is usable from all places where autoClose is called.
Note that as Vitalii Vitrenko point out, this method will swallow the exception from the close method, if both the function supplied by the client, and the close method on the AutoCloseable throws an exception. Javas try-with-resources handles this, and we can make autoClose do so to, by making it a bit more complex:
def autoClose[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): B = {
var t: Throwable = null
try {
fun(closeable)
} catch {
case funT: Throwable ⇒
t = funT
throw t
} finally {
if (t != null) {
try {
closeable.close()
} catch {
case closeT: Throwable ⇒
t.addSuppressed(closeT)
throw t
}
} else {
closeable.close()
}
}
}
This works by storing the potentially exception the client function throws, and adding the potential exception of the close method to it as a supressed exception. This is pretty close to how oracle explains that try-with-resource is actually doing it: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html
However this is Scala, and a lot of people will prefer to program in a more functional way. In a more functional way, the method should return a Try, instead of throwing an exception. This avoids a side effect of throwing an exception, and makes it clear to the client that the response may be a failure that should be handled (as pointed out in the answer by Stas). In a functional implementation, we would also like to avoid having a var, so a naive attempt could be:
// Warning this implementation is not 100% safe, see below
def autoCloseTry[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): Try[B] = {
Try(fun(closeable)).transform(
result ⇒ {
closeable.close()
Success(result)
},
funT ⇒ {
Try(closeable.close()).transform(
_ ⇒ Failure(funT),
closeT ⇒ {
funT.addSuppressed(closeT)
Failure(funT)
}
)
}
)
}
This could them be called like this:
val myTry = autoCloseTry(closeable) { resource ⇒
//doSomethingWithTheResource
33
}
myTry match {
case Success(result) ⇒ doSomethingWithTheResult(result)
case Failure(t) ⇒ handleMyExceptions(t)
}
Or you could just call .get on myTry to make it return the result, or throw the exception.
However as Kolmar points out in a comment, this implementation is flawed, due to how the return statement works in scala. Consider the following:
class MyClass extends AutoCloseable {
override def close(): Unit = println("Closing!")
}
def foo: Try[Int] = {
autoCloseTry(new MyClass) { _ => return Success(0) }
}
println(foo)
We would expect this to print Closing!, but it will not. The problem here is the explicit return statement inside the function body. It makes the method skip the logic in the autoCloseTry method, and thereby just returns Success(0), without closing the resource.
To fix that problem, we can create a mix of the 2 solutions, one that has the functional API of returning a Try, but uses the classic implementation based on try/finally blocks:
def autoCloseTry[A <: AutoCloseable,B](
closeable: A)(fun: (A) ⇒ B): Try[B] = {
var t: Throwable = null
try {
Success(fun(closeable))
} catch {
case funT: Throwable ⇒
t = funT
Failure(t)
} finally {
if (t != null) {
try {
closeable.close()
} catch {
case closeT: Throwable ⇒
t.addSuppressed(closeT)
Failure(t)
}
} else {
closeable.close()
}
}
}
This should fix the problem, and can be used just like the first attempt. However it shows that this a bit error prone, and the faulty implementation has been in this answer as the recommended version for quite some time. So unless you trying to avoid having to many libraries, you should properly consider using this functionality from a library. I think that there is already one other answer pointing to one, but my guess is that there is multiply libraries, that solves this problem in different ways.
Alternatively, you can use Choppy's (Disclaimer: I am the author) TryClose monad do this in a for-comprehension in a composeable manner similar to Scala's Try.
val ds = new JdbcDataSource()
val output = for {
conn <- TryClose(ds.getConnection())
ps <- TryClose(conn.prepareStatement("select * from MyTable"))
rs <- TryClose.wrap(ps.executeQuery())
} yield wrap(extractResult(rs))
Here's how you would do it with your stream:
val output = for {
stream <- TryClose(Files.lines(Paths.get("somefile.txt")))
} yield wrap(stream.findAny())
More info here:
https://github.com/choppythelumberjack/tryclose
You have the already mentioned in one of the answers approach:
def autoClose[A <: AutoCloseable, B](resource: A)(code: A ⇒ B): B = {
try
code(resource)
finally
resource.close()
}
But I think the following is much more elegant:
def autoClose[A <: AutoCloseable, B](resource: A)(code: A ⇒ B): Try[B] = {
val tryResult = Try {code(resource)}
resource.close()
tryResult
}
With the last one IMHO it's easier to handle the control flow.

Expressive Java Function

I have a working Java app that I am looking to update to use more of Java 8's features.
I have a Function as follows:
protected static Function<Notification,Notification>
coverpageNotification = n -> n
.withMessage("COVERPAGE MESSAGE")
.withDate(new Date());
and I call it now using:
s = new HashSet<Notification>();
checkNotificationStatus(true, coverpageNotification.apply(new Notification()), s);
...
...
Instead of saying coverpageNotification.apply(new Notification()), is there a more expressive way of doing this using lambdas?
There is no more expressive syntax to call Function.apply()
Apart from that, what are you trying to achieve with lambdas?
In its current form, this does not have any advantage over a simple method:
static Notifaction addCoverPage(Notifaction n){
return n.withMessage("COVERPAGE MESSAGE")
.withDate(new Date());
}
and
checkNotificationStatus(true, addCoverPage(new Notification()), s);
If you still need a function at some point, you can also turn the method into one:
Function<Notification,Notification> x = SomeClass::addCoverPage;

Categories

Resources