I have a kotlin web request method that takes a function as a parameter.
Due to how one of my classes is set up, I need to keep it as a java class but I need to call the web request method from the java class.
I have a class called Lock that I am fetching from my database using Fuel
My kotlin method is as follows
fun fetchLocks(completion: (Array<Lock>) -> Unit) {
// asynchronous api calls that aren't relevant.
completion(locks)
}
I know that this method works and am able to call it from a kotlin file
FuelHelper().fetchLocks { locks ->
Do stuff with my locks
}
The issue I am having is getting the proper syntax in order to call this method in java.
new FuelHelper().fetchLocks();
The parameter java expects is (Function1<?super Lock[], Unit>)
I have tried for a while now and am unable to get past this. Any help would be appreciated.
Assuming that you are using java 8 syntax.
new FuelHelper().fetchLocks(locks -> {
...
});
Or without lambda
new FuelHelper().fetchLocks(new Function1<Lock[], Unit>() {
#Override
public Unit invoke(Lock[] locks) {
return null;
}
});
It's exactly what it says - You have to pass an object implementing interface Function1 (source from generated file Functions.kt):
/** A function that takes 1 argument. */
public interface Function1<in P1, out R> : Function<R> {
/** Invokes the function with the specified argument. */
public operator fun invoke(p1: P1): R
}
In your case you create an anonymous class the same way you do for all small listeners like onClicks etc.:
new FuelHelper().fetchLocks(new Function1<Lock[], Unit>() {
#Override
public Unit invoke(Lock[] locks) {
// handle locks
return null;
}
});
Related
As I converted this method in Java:
private void enqueueDownloads() {
final List<Request> requests = Data.getFetchRequestWithGroupId(GROUP_ID);
fetch.enqueue(requests, updatedRequests -> {
}, error -> Timber.d("DownloadListActivity Error: %1$s", error.toString()));
}
It led to this method which has a lot of errors:
private fun enqueueDownloads() {
val requests = Data.getFetchRequestWithGroupId(GROUP_ID)
fetch.enqueue(requests, { updatedRequests ->
}, { error -> Timber.d("DownloadListActivity Error: %1\$s", error.toString()) })
}
This method in Kotlin has a lot of errors at the method fetch.enqueue where the value updatedRequestsand error it says Cannot infer a type for this parameter.
So I hit hover on the method and hit Ctrl+B and the method declaration in the library is:
fun enqueue(requests: List<Request>, func: Func<List<Request>>? = null, func2: Func<Error>? = null): Fetch
/** Pause a queued or downloading download.
* #param ids ids of downloads to be paused.
* #param func Callback the paused downloads will be returned on. Note. Only downloads that
* were paused will be returned in the result list.
* #param func2 Callback that is called when attempting to pause downloads fail. An error is returned.
* #throws FetchException if this instance of Fetch has been closed.
* #return Instance
* */
The problem has something to do with CallBack based on the method documentation but I can not get it to work! How can I make it fully Kotlin and call it in Kotlin?.
The library is Fetch2 and written in Kotlin. Also I can not see whole code for the methods in the library.
TLDR: the shortes syntax in your specific case is:
fetch.enqueue(requests, Func { updatedRequests ->
}, Func { error -> Timber.d("DownloadListActivity Error: %1\$s", error) })
The issue here is that you are calling function written in Kotlin. You can't use the short lambda syntax here, since Kotlin will not turn lambdas automatically into the right interface in that case.
"Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported." (source)
Usually to implement (Kotlin) interfaces anonymously in Kotlin you'll have to use the full-blown object Syntax:
interface KFunc<T> { fun call(result: T) }
val func = object : KFunc<String> {
override fun call(result: String) {
println(result)
}
}
However Func is an interface defined in Java so Kotlin offers an automatic conversion utility and you can write
val func: Func<String> = Func {
result -> println(result)
}
This is because there is an automatically generated method for every Java interface. In this case below code is generated
fun <T> Func(function: (result: T) -> Unit): Func<T> {
return object : Func<T> {
override fun call(result: T) {
function(result) // call the function
}
}
}
If the method that takes the Func was also written in Java that's where you can even leave out the Func {} part. E.g. given
public class JavaClass {
public static void doWithFunc(Func<String> func) {
func.call("Hello");
}
}
you could write
JavaClass.doWithFunc { result -> println(result) }
However given
object KotlinClass {
#JvmStatic
fun doWithFunc(func: Func<String>) {
func.call("Hello")
}
}
you must write at least
KotlinClass.doWithFunc(Func { result -> println(result) })
On the other hand from Java(8+) you can use lambdas in both cases
JavaClass.doWithFunc(string -> System.out.println(string));
KotlinClass.doWithFunc(string -> System.out.println(string));
It's a little confusing. At the moment, APIs written in Kotlin that are meant for Kotlin consumption shouldn't use functional interfaces but actual function parameters, i.e. for the enqueue function which is
fun enqueue(requests: List<Request>, func: Func<List<Request>>? = null, func2: Func<Error>? = null): Fetch
they would ideally also offer
fun enqueue(requests: List<Request>, func: ((List<Request>) -> Unit)? = null, func2: ((Error) -> Unit)? = null): Fetch
which would allow you to call it like expected in Kotlin
fixedFetch.enqueue(requests, { println(it) }, { Timber.w(it) })
The downside is that this gives a fairly odd looking method for Java users of the library since Kotlin uses it's Function1 interface to represent function parameters. You'll also have to return Unit.INSTANCE since that's actually a type in Kotlin.
Fetch enqueue(List<? extends Request>, Function1<? super List<? extends Request>, Unit>, Function1<? super Error, Unit>)
The problem is taken from initializing and retrieving data from Firebase, however I will translate this to pseudo in order those who are not familiar could also contribue. Please consider the following code:
`
//Given the following API (from Firebase)
MyRemoteDBClass.asyncAuthenticate(initCompletedListener);
MyRemoteDBClass.asyncDataFetch(fetchCompletedListener)
// of course you have to authenticate before fetching the data
Class MyClassA.init()
{
MyRemoteDBClass myRemoteDBClassInstance = new MyRemoteDBClass();
myRemoteDBClassInstance.asyncAuthenticate(some_listener);
}
// Then somewhere in the app:
Class MyClassB.asyncDataFetch(MyRemoteDBClass myRemoteDBClassInstance){
myRemoteDBClassInstance.asyncDataFetch(myClassBObject_as_listener)
}`
The problem is that the calls of ClassA and ClassB are pretty close in timeline and I don't know if I get to call the asyncFetch before or after the init of myRemoteDBClassInstance was already completed.
How can I promise that I get to call myRemoteDBClassInstance.asyncDataFetch method in MyClassB after the init was completed?
Make your some_listener take a CompletableFuture, and resolve it once the asyncAuthenticate is complete. It would end up looking something like this:
CompletableFuture<Void> future = new CompletableFuture<>();
Listener some_listener = new Listener() {
#override onAuthComplete() { future.complete(null); }
//...
};
// Guts of your MyClassA.init
MyRemoteDBClass myRemoteDBClassInstance = new MyRemoteDBClass();
myRemoteDBClassInstance.asyncAuthenticate(some_listener);
// ...
// Guts of your MyClassB.asyncDataFetch
future.get(); // Wait for auth to complete
myRemoteDBClassInstance.asyncDataFetch(other_listener);
I like to use a future, since it allows us to return something more useful than a Void later, or to perform chaining of async calls nicely later.
I would initialize a state in MyClassA, to keep a record whether it is initialized. Then check this state in MyClassB.
Class MyClassA.init()
{
MyRemoteDBClass myRemoteDBClassInstance = new MyRemoteDBClass();
myRemoteDBClassInstance.asyncAuthenticate(some_listener);
static boolean initialized = true;//only sample code
}
static boolean MyClassA.isInitialized() {return initialized ;}
// Then somewhere in the app:
Class MyClassB.asyncDataFetch(MyRemoteDBClass myRemoteDBClassInstance){
if (MyClassA.isInitialized()) { //only sample code
myRemoteDBClassInstance.asyncDataFetch(myClassBObject_as_listener)
}
}
I am new to Scala and I need to have a scala wrapper for my Java API
I have three Java Interfaces
public interface Client<T> {
<T> Future<T> execute(App<T> app);
}
public interface App<T> extends Serializable{
T process(AppContext context) throws Exception;
}
public interface AppContext {
File getDirectory();
void deleteDirectory();
File createDirectory(String path);
}
Following is the Java code to create an App
public class RandomApp extends App<String> {
#Override
public String process(AppContext context) {
// Inorder to access the methods in AppContext I need to access
// it by the following way
appContext.createDirectory("some path");
return "random";
}
}
I want to have a Scala Wrapper for the Client Interface which in turn call the Java API. But I have some modifications for the new Scala API
object ScalaConverter {
implicit class ScalaWrapper(client: Client) {
def scalaClient = new ScalaClient(client)
}
}
class ScalaClient(client: Client) {
def execute[T](appContext: AppContext => T): Future[T] = {
// I am passing appContext as closure instead of passing in
// App because I want to take the advantage of Closures in Scala
// I basically want to create an App with this appContext and
// pass it to the execute method
// For example - but this is not working
var app = // Need to create this app with appContext
Future {
client.execute(app)
}
}
}
If I'm not mistaken, you just want to be able to create App objects from a function that takes a AppContext as parameter and returns a any object (let's say T).
As it's not really interesting to try to mirror the whole java API, just use it as it is, but add some extensions. And to do this you should use implicits.
To do this, I see two possibilities: either add an implicit class on the Client interface to add some functions to it, or add an implicit conversion from (AppContext => T) to App objects.
Let's got with the first solution, you have to embed the implicit class in an object (this can be a package object if you need automatic imports).
object ScalaConverter {
class ScalaApp[T](val block: AppContext => T) extends App[T] {
def process(context: AppContext): T = block(context)
}
implicit class ScalaClient(client: Client) extends AnyVal{
def execute[T](block: AppContext => T): Future[T] = {
client.execute(new ScalaApp(block))
}
}
}
Then, you just have to use your existing java Client object:
import ScalaConverter._
myJavaClient.execute { context =>
???
}
You should get the principle, I maybe made a mistake (did not tried to compile this)
I'd like to see how this Java code would look in JRuby:
ParseQuery query = new ParseQuery("MyClass");
query.getInBackground(myId, new GetCallback() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
objectWasRetrievedSuccessfully(object);
} else {
objectRetrievalFailed();
}
}
});
The biggest part of confusion for me is the anonymous inner class. This is my best first guess:
query = ParseQuery.new("GameScore")
query.getInBackground("xWMyZ4YEGZ", Class.new(GetCallback) do
def done(object, e)
# ...
end
end.new)
Update: Edited based on this: http://www.ruby-forum.com/topic/188599#823271
The syntax for expressing this in JRuby is deceptively simple. JRuby has a feature called 'closure conversion' where a closure passed to a method can is converted into the appropriate Java interface. From the JRuby docs:
This not only works for event listeners or Runnable, but basically for any interface. When calling a method that expects an interface, JRuby checks if a block is passed and automatically converts the block to an object implementing the interface.
So, your code would look like:
query.in_background 'xWMyZ4YEGZ' { |object, e|
# do stuff
}
The 'calling Java from JRuby' page on the JRuby wiki is a good resource for problems like these.
For public method calls, EasyMock's capture() allows you to intercept & examine arguments passed to the method. For private method calls, PowerMock's expectPrivate lets you mock private method calls.
Is there a way to somehow combine these and get the arguments passed to a private method call? Example:
public class Program
{
public FancyReturnType PublicMethod()
{
ArbitraryType localInstance = new ArbitraryType();
localInstance.setFoo(somePrivateHelperMethod());
localInstance.setBar(increasinglyComplexMagic());
long aLongValue = 11235L;
// more variables, more work
SomeType worker = privateHelperToIntercept(localInstance, aLongValue, otherVariables);
if (worker.something)
{
return retVal.aFancyReturnType;
}
else
{
return retVal.anotherFancyReturnType;
}
}
}
In this case, I want to examine the localInstance object as it is consumed by the privateHelperToIntercept() call.
I've found plenty of examples to mock private method calls; PowerMock's expectPrivate(partiallyMockedObject, "nameOfPrivateMethod", arg1, arg2) works great. I've also found examples to intercept arguments passed to public method calls; Capture<Type> myTestCapture = new Capture<Type>() combined with someMockedObject.PublicMethod(capture(myTestCapture)).
Unfortunately, I can neither get the two to work together, nor find examples of combining them. Has anyone seen a way to do this?
FWIW, I suspect Mockito can do this, but it's not included in our source/build/test system. I'd like to avoid the process of supporting new libraries in our system if possible.
If you are asking how to get a reference to localInstance, then the following code should suffice.
#PrepareForTest(Program.class)
public class Test {
#Test
public void testMethod() {
ArbitraryType passedLocalInstance = new ArbitraryType();
PowerMock.expectNew(ArbitraryType.class).andReturn(passedLocalInstance );
//remainder of the test method
assertEquals(14.2, passedLocalInstance .getValue());
}
}
Since java is pass-by-reference, the passedLocalInstance will be the argument passed into the method call. Did that answer your question?
new of any type is simply a static method. Deal with it in the same way... wrap it in a method, stub out the method. In this case you want to return a mock in your test, and then you can test all the interactions with that object (and remove dependency in your test on the code within the object you are creating which should have it's own tests)
public Program {
// your above code up to object creation
ArbitraryType localInstance = createArbitraryType();
// rest of your above code here
ArbitraryType createArbitraryType() {
return new ArbitraryType();
}
}
in your test...
public class MyTest {
TestableProgram extends Program {
#Override
ArbitraryType createArbitraryType() {
return this.arbitraryTypeMock;
}
}
private ArbitraryType arbitraryTypeMock;
private TestableMyClass objectToTest = new TestableProgram();
// rest of your tests...
}
Given your constraint's that's how I'd do it.
If could bend your constraints a bit I'd loosen up on the private methods, I've generally done away with private in favor of package default to make testing easier. If the folks IN your package are misbehaving, it's usually your code so private is mostly protecting you from yourself anyway. (but I know that isn't a valid answer your question as posed... ).