I have two questions about Android Callable Wrappers which I hope you guys could answer.
Question 1. Xamarin auto-generates the following constructor in the ACW of a class:
public ConsumerService (java.lang.String p0, android.content.Context p1)
{
super (p0, p1);
if (getClass () == ConsumerService.class)
mono.android .TypeManager.Activate ("Test.Tizen.Droid.ConsumerService, Test.Tizen.Droid", "System.String, mscorlib:Android.Content.Context, Mono.Android ", this, new java.lang.Object[] { p0, p1 });
}
But then throws following exception on startup of the app: System.TypeLoadException: Could not load type '.mscorlib' from assembly 'Mono.Android , Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065'.
Which references to this part in the constructor: mscorlib:Android.Content.Context. Removing the "mscorlib:" fixes the exception, but my question is, why does it throw an exception in the first place since Xamarin auto-generates this?
Question 2. Can anyone tell me why Xamarin only takes the base class into account when generating the ACW of a derived class, and doesn't take the constructors of the derived class into account?
I created a Xamarin Binding Project for Android, and generated the Bindings for the .aar file. So far, so good.
When I first called a constructor which throws an Exception, a build error occured:
.../XamVideoCaptureReader.java(9,9): Error: error: unreported exception ReaderException; must be caught or declared to be thrown super (p0, p1, p2); (AndroidTest)
On the following code part:
public XamVideoCaptureReader (int p0, com.digimarc.dms.readers.ReaderOptions p1, com.digimarc.dms.readers.image.CaptureFormat p2)
{
super (p0, p1, p2);
...
}
I think the error is pretty self explanatory, but I can't find a way to fix it. The super call has to be wrapped in a try catch, or even better: a throws ReaderException should be added to the constructor signature.
Has anyone experienced this error before and could solve it? Or is this a bug of Xamarin?
protected void init() {
getApplicationSettings().setInternalErrorPage(BnafInternalErrorPage.class);
getApplicationSettings().setPageExpiredErrorPage(BnafAccessDeniedErrorPage.class);
getApplicationSettings().setAccessDeniedPage(BnafAccessDeniedErrorPage.class);
getExceptionSettings().setInternalErrorPage(IExceptionSettings.SHOW_INTERNAL_ERROR_PAGE);
In above code i got error at IExceptionSettings.
IExceptionSettings removed in wicket 7
So you can replace this below line.
getExceptionSettings().setInternalErrorPage(IExceptionSettings.SHOW_INTERNAL_ERROR_PAGE);
to
getExceptionSettings().setUnexpectedExceptionDisplay(ExceptionSettings.SHOW_INTERNAL_ERROR_PAGE);
To know more details check here
https://cwiki.apache.org/confluence/display/WICKET/Migration+to+Wicket+7.0#MigrationtoWicket7.0-AllIXyzSettingsareremovedWICKET-5410
I have my service declared this way:
public interface BlogQueryService extends Service {
public ServiceCall<String, Source<String, ?>> tick(int interval);
public ServiceCall<String, Source<String, ?>> tock();
public ServiceCall<NotUsed, Source<PostSummary, ?>> newPosts();
public ServiceCall<String, Source<PostSummary, ?>> getPostSummaries();
#Override
default Descriptor descriptor() {
return named("blog-query").with(
//pathCall("/api/bloggie/tick/:interval", this::tick),
pathCall("/api/bloggie/tock", tock())
//pathCall("/api/bloggie/newPosts", this::newPosts),
//pathCall("/api/bloggie/postSummaries", this::getPostSummaries)
).withAutoAcl(true);
}
}
The tick works. The tock doesn't.
When I invoke it using websocket client (to ws://localhost:9000/api/bloggie/tock ) , I got "undefined" as response, indicating no mapping found for that URL.
After some experimentings, found out why: tick works because it has url param (the :interval). Tick doesn't work because it doesn't have url param. Seriously pathCall requires you to have param in your URL? So I checked the API of Service: http://www.lagomframework.com/documentation/1.0.x/api/java/com/lightbend/lagom/javadsl/api/Service.html
There are several overloaded declarations of pathCall. Apparently the tick uses this one:
static <Request,Response,A> Descriptor.Call<Request,Response> pathCall(String pathPattern, akka.japi.function.Function<A,ServiceCall<Request,Response>> methodRef)
So from the signature, yes it requires the method to take a parameter. So, if the method (such is tock) doesn't take a param, the binding will fail at runtime. So I guess I need to use this one instead:
static <Request,Response> Descriptor.Call<Request,Response> pathCall(String pathPattern, akka.japi.function.Creator<ServiceCall<Request,Response>> methodRef)
The problem is... I don't know how. I haven't seen any example of the use of akka.japi.function.Creator in pathCall.
I tried this:
default Descriptor descriptor() {
return named("blog-query").with(
pathCall("/api/bloggie/tick/:interval", this::tick),
pathCall("/api/bloggie/tock", new Creator<ServiceCall<String, Source<String, ?>>> () {
public ServiceCall<String, Source<String, ?>> create() {
return tock();
}
})
//pathCall("/api/bloggie/newPosts", this::newPosts),
//pathCall("/api/bloggie/postSummaries", this::getPostSummaries)
).withAutoAcl(true);
}
It compiles. But it throws an error at runtime:
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, java.lang.IllegalStateException: Unable to resolve method for service call with ID PathCallId{pathPattern='/api/bloggie/tock'}. Ensure that the you have passed a method reference (ie, this::someMethod). Passing anything else, for example lambdas, anonymous classes or actual implementation classes, is forbidden in declaring a service descriptor.
at com.lightbend.lagom.javadsl.server.ServiceGuiceSupport.bindServices(ServiceGuiceSupport.java:43) (via modules: com.google.inject.util.Modules$OverrideModule -> sample.bloggie.impl.BlogServiceModule)
while locating com.lightbend.lagom.internal.server.ResolvedServices
Thanks in advance!
I just did some experiments... All compiled, but none of them works....
namedCall("/api/bloggie/tock", this::tock)
Result: Compile success. Runtime: path unknown (no binding (?)).
Then I tried
pathCall("/api/bloggie/tock", () -> this.tock())
Result: exception.
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, scala.MatchError: Request (of class sun.reflect.generics.reflectiveObjects.TypeVariableImpl)
at com.lightbend.lagom.javadsl.server.ServiceGuiceSupport.bindServices(ServiceGuiceSupport.java:43) (via modules: com.google.inject.util.Modules$OverrideModule -> sample.bloggie.impl.BlogServiceModule)
while locating com.lightbend.lagom.internal.server.ResolvedServices
for parameter 1 at com.lightbend.lagom.internal.server.ServiceRegistrationModule$RegisterWithServiceRegistry.<init>(ServiceRegistrationModule.scala:55)
at com.lightbend.lagom.internal.server.ServiceRegistrationModule.bindings(ServiceRegistrationModule.scala:29):
Binding(class com.lightbend.lagom.internal.server.ServiceRegistrationModule$RegisterWithServiceRegistry to self eagerly) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
while locating com.lightbend.lagom.internal.server.ServiceRegistrationModule$RegisterWithServiceRegistry
Then I tried:
public ServiceCall<NotUsed, Source<String, ?>> tock(Void x);
Result: exception
com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, java.lang.IllegalArgumentException: Don't know how to serialize ID class java.lang.Void
at com.lightbend.lagom.javadsl.server.ServiceGuiceSupport.bindServices(ServiceGuiceSupport.java:43) (via modules: com.google.inject.util.Modules$OverrideModule -> sample.bloggie.impl.BlogServiceModule)
Update: "Solved" (partially). Figured out that this one works:
pathCall("/tock", this::tock)
I can open it using this URL: ws://localhost:9000/tock
So..., I can't have nicely structured URL for those functions that returns stream, when those functions need no param? At least for now (?).
UPDATE: seems like this problem is happening not only with pathCall. I encountered the same problem with rest call. This one doesn't work (no binding):
public ServiceCall<NotUsed, PSequence<PostSummary>> getPostSummaries();
...
restCall(Method.GET, "/api/bloggie/postSummaries", this::getPostSummaries)
This one works:
public ServiceCall<NotUsed, PSequence<PostSummary>> getPostSummaries();
...
restCall(Method.GET, "/postSummaries", this::getPostSummaries)
Thanks!
So firstly, namedCall should only be used if you don't care about the path. You are invoking the service call directly, which means you do care about the path, so you have to use pathCall or restCall.
This should work:
pathCall("/api/bloggie/tock", this::tock)
Also, I think you're not pasting the full errors. Make sure you check right to the bottom of the list of Guice errors, that should explain exactly what the problem is, in many of the cases above, the problem is that you're not passing a method reference, you're passing a lambda, and the error message should say that.
Can anyone shed any light as to why the following code would crash in the release version of an Xcode 6 build but not in the debug version ?
Can I cast this as something to try and prevent this
// Check if iCloud is enabled
if let currentToken = NSFileManager.defaultManager().ubiquityIdentityToken {
// The following line causes a crash in Release version
FLOG(" currentUbiquityIdentityToken is \(currentToken)")
EDIT:
More digging and the problem was caused by this code when the "DataModel" name had been changed to something else. I would have expected the "let modelURL = NSBundle." line to have thrown an exception but it does not. Seems it was just pure coincidence that the debugger was on the "FLOG(...)" line of code when the bad access exception gets thrown.
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = NSBundle.mainBundle().URLForResource("DataModel", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()