Porting Java to C# for Xamarin Android Library - java

I created an Android Binding Library for my Xamarin project, using an AAR.
I am now trying to implement that library.
Here is the java snippet of code using the library:
The java code:
new AsyncOperation.CompletionHandler<RouteManager>(){
#Override
public void success(RouteManager result){
result.subscribe(ACCEL_DATA, new RouteManager.MessageHandler(){
#Override
public void process(Message message){
Log.i(LOG_TAG,message)
}
}
}
I am trying to port this code to C#.
My C# code, from C# wrapper created from binding library:
class AsyncOperationHandler : AsyncOperationCompletionHandler
{
public override unsafe void Success(Object p0)
{
try
{
var routeManger = (IRouteManager)p0;
routeManger.Subscribe(ACCEL_DATA, new RouteMessageHandler());
}
catch (Exception)
{
Log.Error(LOG_TAG, "Error");
}
}
}
class RouteMessageHandler : IRouteManagerMessageHandler
{
public void Dispose()
{
throw new NotImplementedException();
}
public IntPtr Handle { get; }
public void Process(Message p0)
{
var message = p0;
Log.Info(LOG_TAG, message);
}
}
I am getting an error in the C# wrapper on the routeManger.Subscribe line.
When the RouteManagerMessageHandler gets initialized, it gets the Handle, then throws a null pointer exception inside the Binding Library.
Is this the correct way to port a Java Interface to C#?

If you implement a Java Interface, you have to derive from Java.Lang.Object.
class RouteMessageHandler : Java.Lang.Object, IRouteManagerMessageHandler
{
public void Process(Message p0)
{
var message = p0;
Log.Info(LOG_TAG, message);
}
}
There should be something on the compile output.
Type 'AppXYZ.RouteMessageHandler' implements IRouteManagerMessageHandler but does not inherit from Java.Lang.Object. It is not supported.

Related

Is it possible to override a method from interface at runtime?

I wonder if it is possible to override a method from an interface. I'm developing a plugin application for Confluence Data Center, and I need to maintain backward compatibility with the older version of Confluence, some of the interfaces are only available in the latest version of Confluence SDK, and I need to implement it dynamically(check the version, if it's an old version, use old interface)
this is the interface I need to implement:
public interface SiteSearchPermissionsQueryFactory {
SearchQuery create();
}
I have a class implementing the interface:
public class SiteSearchPermissionQueryFactory implements SiteSearchPermissionsQueryFactory {
final private SearchQuery searchQuery;
public SiteSearchPermissionQueryFactory(SearchQuery searchQuery){
this.searchQuery = searchQuery;
}
#Override
public SearchQuery create() {
return searchQuery;
}
}
As SiteSearchPermissionsQueryFactory is a new interface and only available on the latest version of Confluence SDK, and now I need to implement this interface and its override method create() dynamically on runtime(if my plugin application runs on latest version of Confluence).
I can check the instance of SiteSearchPermissionsQueryFactory like this:
public static SearchQuery getCompatibleQuery() {
try {
Class<?> permissionQueryFactory = Class.forName("SiteSearchPermissionsQueryFactory");
Object instance = Proxy.newProxyInstance(permissionQueryFactory.getClassLoader(), new Class<?>[]{permissionQueryFactory}, new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//Handle the invocations
if(method.getName().equals("create")){
return 1;
}
else return -1;
}
});
} catch (Exception e) {
return null;
}
}
But I have no idea how to override the create() method. Any help would be appreciated!

JNA callback function with additional argument

I have got problem getting JNA all worked out. I am trying to invoke a function that takes as a arguments pointer to function and const char*. My C code looks like this:
typedef void (*example_ptr)(const char*);
void exampleMethod(const char* value)
{
printf("This is the string: %s\n", value);
}
void example_triggerCallback(const example_ptr func, const char* str) {
printf("provided str: %s", str);
func(str);
}
To get this going I wrote such JNA wrapper in Java
public class Main {
public interface TestLibrary extends Library {
TestLibrary INSTANCE = (TestLibrary)
Native.loadLibrary("libtest",
TestLibrary.class);
interface ExampleCallback extends Callback {
void invoke(String str);
}
class ExampleCallbackImpl implements ExampleCallback {
public void invoke(String str) {
System.out.println("example: " + str);
}
}
void example_triggerCallback(ExampleCallback callback, String str);
}
public static void main(String[] args) {
TestLibrary testLibrary = TestLibrary.INSTANCE;
final TestLibrary.ExampleCallbackImpl callback = new TestLibrary.ExampleCallbackImpl();
testLibrary.example_triggerCallback(callback, "testiddy test test");
}
}
The problem I am facing is that the printf in example_triggerCallback in C code is in fact being called and I am getting the output on Java console but what I am really trying to achieve here is that I would like to pass from Java side the pointer for the exampleMethod from C so it would be printing the passed String. Right now func(str) seems to be ignored. What am I missing here?
Based on something found in JNA documentation:
typedef void (*ExampleCallback)(const char*);
void exampleMethod(const char* value)
{
printf("This is the string: %s\n", value);
}
void example_triggerCallback(const example_ptr func, const char* str) {
printf("provided str: %s", str);
func(str);
}
public interface CLibrary extends Library {
// define an interface that wraps the callback code
public interface ExampleCallbackInterface extends Callback {
void invoke(String val);
}
// functions available in library (name must match)
public void exampleMethod(String value);
public void example_triggerCallback(ExampleCallbackInterface callback);
}
// define an implementation of the callback interface
public static class CallbackExample implements Example22CallbackInterface {
private CLibrary lib;
public CallbackExample(CLibrary useLib) {
lib = useLib;
}
#Override
public void invoke(String val) {
lib.exampleMethod(val);
}
}
...
final CLibrary clib = (CLibrary)Native.loadLibrary("testlib", CLibrary.class);
...
// instantiate a callback wrapper instance
final CallbackExample callback = new CallbackExample(clib);
// pass the callback wrapper to the C library
clib.example_triggerCallback(callback);
Since I answered this question in some other internet location, I know that it works for the questioner.

Java - How to test exception which never will occur?

I have Utils class with method which throws exception when given data are incorrect.
I have also Service which uses this method, but the data are always generated in way that they will be correct during call. Data are generated by another utils class.
I understand that I should throw this exception from Utils class - but I can't throw it from Service - so I have to catch it.
How can I test this, simulate this exception?
All actions on this data are in private methods.
I want to avoid PowerMock, because I heard that it's a sign of bad design.
So the question is, how to implement this in good design?
From your description it looks like this:
class Service {
public void someMethod() {
Data data = AnotherUtils.getData();
try {
Utils.method(data); // exception never thrown
} catch(Exception e) {
// how to test this branch?
}
}
}
The goal would be something like this:
interface DataProvider {
Data getData();
}
interface DataConsumer {
void method(Data data);
}
class Service {
private final DataProvider dataProvider;
private final DataConsumer dataConsumer;
public Service(DataProvider dataProvider, DataConsumer dataConsumer) {...}
public void someMethod() {
Data d = dataProvider.getData();
try {
dataConsumer.method(data);
} catch(Exception e) {
}
}
}
This technique is called dependency injection.
Then, when testing, you can simply provide a mock implementation for this DataProvider interface that does return faulty data:
#Test(expected=Exception.class)
public void myTest() {
DataProvider badDataProvider = () -> new BadData(); // Returns faulty data
Service service = new Service(badDataProvider, Utils.getConsumer());
service.someMethod(); // boom!
}
For the non-testing code, you could simply wrap the utils classes you already have in these interfaces:
class AnotherUtils {
public static Data getData() {...}
public static DataProvider getProvider() {
return AnotherUtils::getData;
}
}
...
Service service = new Service(AnotherUtils.getProvider(), Utils.getConsumer());
Here is an approach where you want to introduce Dependency Injection, but for whatever reason you don't want to change legacy code.
Say you have some static utility method like so:
class Utils{
public static Something aMethod(SomethingElse input) throws AnException{
if(input.isValid())
return input.toSomething();
throw new AnException("yadda yadda");
}
}
And you have a class that uses that utility method. You can still inject it with a FunctionalInterface.
#FunctionalInterface
interface FunctionThrowsAnException<K,V> {
V apply(K input) throws AnException;
}
class Service {
private final FunctionThrowsAnException<SomethingElse,Something> func;
Service(FunctionThrowsAnException<SomethingElse,Something> func){
this.func = func;
}
Something aMethod(SomethingElse input){
try{
return func.apply(input);
}catch(AnException ex){
LOGGER.error(ex);
}
}
}
Then use it like this:
new Service(Utils::aMethod).aMethod(input);
To test it:
new Service(x -> { throw new AnException("HA HA"); }).aMethod(input);

How do I write this without 'retrolambda' syntax?

I am 100% new to Java and I'm trying to add Crashlytics to my React Native project. The only code snippet I could find on the internet is retrolambda syntax.
I realize I could add that particular "library" or whatever, so it works, but considering it's the only place used in my project I'd rather just convert it to the 'older format' rather than adding a library just to do one function.
public final class AppReactPackage implements ReactPackage {
#Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
addExceptionHandler(reactContext);
}
private void addExceptionHandler(ReactApplicationContext reactContext) {
// Fyi, this is using Retrolambda for Java 8 syntax
reactContext.setNativeModuleCallExceptionHandler(e -> {
if (e instanceof JavascriptException) {
Crashlytics.log(e.getMessage());
} else {
Crashlytics.logException(e);
}
});
}
}
Searching your syntax I found these two links:
React
NativeModuleCallExceptionHandler
By using those, it should look something like this: (untested)
private void addExceptionHandler(ReactApplicationContext reactContext) {
reactContext.setNativeModuleCallExceptionHandler(new NativeModuleCallExceptionHandler() {
#Override
public void onHandleException(Exception e) {
if (e instanceof JavascriptException) {
Crashlytics.log(e.getMessage());
} else {
Crashlytics.logException(e);
}
}
});
}

How to pass and invoke method references in Java

Let's say I have a class called Server, and I would like to allow others to write Plugins for it. Say Plugin is an Interface that extends Runnable and adds a single method: void init(...). It is the job of a plugin to collect data and send it to the server. When the time comes to send data to the server, however, how does it do this? Coming from C and C++ I am looking for a thinking along the lines of a function pointer. It seems to be possible in Java though I have not found examples outside the Java Standard Class Library.
How do I pass a method reference to the init method such that it can be stored by the Plugin, and then how do I invoke the method whenever the Plugin wants to send data? For now say that the desired Server method is: void sendData(Integer data).
For example:
// Inside Server
Plugin p = new PluginImplementation();
p.init(this::sendData);
// Plugin init
public void init(?? sendMethod) {
storedSendMethod = sendMethod;
// ...
}
// Plugin run
public void run() {
// ...
storedSendMethod(x) // Sends data to server
// ...
}
Using java.util.function.Function we can pass a function as an argument to a method, and then use apply() to apply it to the relevant arguments. Here's an example:
import java.util.function.Function;
public class FunctionDemo {
// we will pass a reference to this method
public static Integer square(Integer x) {
return x * x;
}
// this method accepts the function as an argument and applies it to the input: 5
public static Integer doSomething(Function<Integer, Integer> func) {
return func.apply(5);
}
public static void main(String[] args) {
// and here's how to use it
System.out.println(doSomething(FunctionDemo::square)); // prints 25
}
}
Additional version with multiple parameters (passed as an array):
public static Integer sum(Integer[] x) {
Integer result = 0;
for(int i = 0; i < x.length; i++)
result += x[i];
return result;
}
public static void main(String[] args) {
Integer[] arr = {1,2,3,4,5};
System.out.println(doSomething(Play::sum, arr));
}
public static Integer doSomething(Function<Integer[], Integer> func,
Integer[] arr) {
return func.apply(arr);
}
If the method is void sendData(Integer data) that corresponds to a consumer that takes an Integer and returns a void which is covered by the built in Consumer<Integer> interface which has an accept(Integer) method that will invoke your function when called.
So your code will look like this:
public void init(Consumer<Integer> sendMethod) {
storedSendMethod = sendMethod;
// ...
}
// Plugin run
void run() {
// ...
storedSendMethod.accept(x) // Sends data to server
// ...
}
As a sidenote, having an init method is probably a bad Java design. you are better moving the initialization to the constructor if possbile
Plugin p = new PluginImplementation( this::sendData);
In java, you do it with a callback,
This is your callback interface,
public interface SendCallback {
public void doSend(Object toSend);
}
This is the plugin interface, All plugin must implement this interface
public interface Plugin extends Runnable {
public void init(SendCallback callback);
}
This is the Server's code.
public class Server {
Plugin plugin;
SendCallback callback = new SendCallback() {
public void doSend(Object toSend) {
// logic to send object 'toSend'
}
}
public Server() {
plugin = new MyPlugin();
plugin.init(callback);
}
}
This is your plugin implementation.
public class MyPlugin implements Plugin {
SendCallback callback = null;
Object x = null;
public void init(SendCallback callback) {
this.callback = callback;
}
public void run() {
x = "Somthing"; // initialize the x object
callback.doSend(x);
}
}
You will notice, the server define the callback implementation.
The plugin will invoke the callback's method doSend.
I hope, this helps
There is method reference in Java 8, however you can just pass a whole object and call its sendData() method. In a 'plug-in' situation, using interfaces for each helps the plugin and the server have 'looser' coupling.
public interface Server {
void setData(...);
}
public class MyPlugin implements plugin {
private Server server;
void init(Server s ) {
this.server = s;
}
void run() {
...
this.server.setData(...);
...
}
}
interface Server{
...
void sendData(String message);
}
Plugin doesn't need a function reference, you can use the Server interface for informing Plugin to know about that method.
class PluginX implements Plugin{
...
private Server server;
void init(Server server) {
this.server = server;
}
public void run() {
// ...
server.sendData(x) // Sends data to server
// ...
}
}

Categories