How do I pass a class to a method in Nashorn? - java-8

One of our scripts has the following line, calling a method in Ant to get a provider:
var provider = resource.as(org.apache.tools.ant.types.resources.FileProvider);
Since updating to Java 8, this now fails with an error:
java.lang.ClassCastException: Cannot cast jdk.internal.dynalink.beans.StaticClass to java.lang.Class
at sun.invoke.util.ValueConversions.newClassCastException(ValueConversions.java:461)
at sun.invoke.util.ValueConversions.castReference(ValueConversions.java:456)
at jdk.nashorn.internal.scripts.Script$\^eval\_.getFileHack(<eval>:131)
at jdk.nashorn.internal.scripts.Script$\^eval\_.runScript(<eval>:207)
I'm trying to figure out what has changed from the Nashorn docs, but it isn't particularly clear. The following change to use what I see in the documented examples gives the same error:
var provider = resource.as(Java.type("org.apache.tools.ant.types.resources.FileProvider"));
How do I convert a StaticClass to a Java Class to pass it in here?

Use .class:
var provider = resource.as(org.apache.tools.ant.types.resources.FileProvider.class);
or
var provider = resource.as(Java.type("org.apache.tools.ant.types.resources.FileProvider").class);
Just like in Java :-)

Related

Problem with Protostream and UUID in Infinispan 13.0.0.Final

I'm using Infinispan 13.0.0.final with the default marshaller (protobuf). When I try to use UUID fields in my datatypes
data class CounterState(
#get:ProtoField(number = 1) var index: Long? = null,
#get:ProtoField(number = 2) var uuid: UUID? = null
)
I get the following error at build time:
.../gradle-kotlin-protobuf/build/tmp/kapt3/stubs/main/io/radiosphere/ProtoSchema.java:8: error: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: The class java.util.UUID must be instantiable using an accessible no-argument constructor.
public abstract interface ProtoSchema extends org.infinispan.protostream.GeneratedSchema {
It seems like I'm not allowed to use UUID in my types unless I generate a protoschema for it, but since UUID is a class outside of my control I can't do this.
Previous questions on the topic have gotten the suggestion to use the JavaSerializationMarshaller, but I want to solve this while still using the Protostream Marshaller. It has also been suggested that this would be fixed in version 12.0.0 here.
An example of this not working can be found here. Note that this project will not build because of the annotation processing failing as mentioned above. If it would build the proof that it is working would be shown by running the main project (ie. not the tests).
The question becomes: What do I need to do to configure UUID to be usable in my protobuf marshalled classes in Infinispan 13? Both for embedded and for a program using the hotrod client?
EDIT:
Based on a given answer I have also tried doing the following:
#AutoProtoSchemaBuilder(
includeClasses = [UUIDAdapter::class, CounterState::class],
schemaPackageName = "tutorial")
interface ProtoSchema : GeneratedSchema {
}
This makes the build work, but when starting Quarkus I get the following error:
Caused by: org.infinispan.protostream.DescriptorParserException: Duplicate type id 1005 for type org.infinispan.protostream.commons.UUID. Already used by tutorial.UUID
at org.infinispan.protostream.descriptors.ResolutionContext.checkUniqueTypeId(ResolutionContext.java:151)
at org.infinispan.protostream.descriptors.ResolutionContext.addGenericDescriptor(ResolutionContext.java:97)
at org.infinispan.protostream.descriptors.FileDescriptor.collectDescriptors(FileDescriptor.java:313)
at org.infinispan.protostream.descriptors.FileDescriptor.resolveDependencies(FileDescriptor.java:245)
at org.infinispan.protostream.descriptors.FileDescriptor.resolveDependencies(FileDescriptor.java:210)
at org.infinispan.protostream.descriptors.ResolutionContext.resolve(ResolutionContext.java:57)
at org.infinispan.protostream.impl.SerializationContextImpl.registerProtoFiles(SerializationContextImpl.java:127)
at org.infinispan.protostream.types.java.CommonTypesSchema.registerSchema(CommonTypesSchema.java:49)
at org.infinispan.client.hotrod.RemoteCacheManager.registerSerializationContextInitializer(RemoteCacheManager.java:422)
at org.infinispan.client.hotrod.RemoteCacheManager.registerDefaultSchemas(RemoteCacheManager.java:437)
at org.infinispan.client.hotrod.RemoteCacheManager.initializeProtoStreamMarshaller(RemoteCacheManager.java:409)
at org.infinispan.client.hotrod.RemoteCacheManager.actualStart(RemoteCacheManager.java:365)
at org.infinispan.client.hotrod.RemoteCacheManager.start(RemoteCacheManager.java:334)
at org.infinispan.client.hotrod.RemoteCacheManager.<init>(RemoteCacheManager.java:192)
at org.infinispan.client.hotrod.RemoteCacheManager.<init>(RemoteCacheManager.java:149)
at io.quarkus.infinispan.client.runtime.InfinispanClientProducer.initialize(InfinispanClientProducer.java:68)
If I instead change to use dependsOn like this:
#AutoProtoSchemaBuilder(
includeClasses = [CounterState::class],
dependsOn = [org.infinispan.protostream.types.java.CommonTypes::class, org.infinispan.protostream.types.java.CommonContainerTypes::class],
schemaPackageName = "tutorial")
I'm back to the build failing with:
error: org.infinispan.protostream.annotations.ProtoSchemaBuilderException: The class java.util.UUID must be instantiable using an accessible no-argument constructor.
public abstract interface ProtoSchema extends org.infinispan.protostream.GeneratedSchema {
It seems to be like Quarkus and the Annotation processor are getting in each others way here when it comes to having a simple working solution for UUID marshalling.
You have to include the org.infinispan.protostream.types.java.util.UUIDAdapter class in your annotation:
#AutoProtoSchemaBuilder(includeClasses = [CounterState::class, UUIDAdapter::class] , schemaPackageName = "tutorial")
For more info, check the documentation page.

Firestore's WriteBatch.update() won't take angularfirestore2's AngularFirestoreDocument

I'm trying to do a batch write using Firestore's WriteBatch. I'm trying to add updates to the WriteBatch and that requires a DocumentReference. I have a AngularFirestoreDocument and can't figure out how to cast that to a DocumentReference and get it to compile or run correctly.
I've tried to cast it to any,unknown, and DocumentReference and use the AngularFirestoreDocument as is.
export class FinancialService {
private transCollection: AngularFirestoreCollection<Transaction>;
batch_update_trans(trans) {
let writer = this.afs.firestore.batch();
this.transCollection = this.afs.collection<Transaction>('balance_sheets/'+this.balance_sheet_id+"/transactions/");
for (let t of trans) {
writer.update(this.transCollection.doc(id),t);
}
return writer.commit();
}
}
if I include the AngularFirestoreDocument as is like above I get this compile time error:
error TS2345: Argument of type 'AngularFirestoreDocument<{}>' is not assignable to parameter of type 'DocumentReference'.
Type 'AngularFirestoreDocument<{}>' is missing the following properties from type 'DocumentReference': id, firestore, parent, path, and 2 more.
If I cast the AngularFirestoreDocument to a DocumentReference:
writer.update(<DocumentReference>this.transCollection.doc(id),t);
I get this compile time error:
error TS2352: Conversion of type 'AngularFirestoreDocument<{}>' to type 'DocumentReference' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type 'AngularFirestoreDocument<{}>' is missing the following properties from type 'DocumentReference': id, firestore, parent, path, and 2 more
If I cast the AngularFirestoreDocument to a DocumentReference to unknown:
writer.update(<unknown> this.transCollection.doc(id),t);
It fails to compile with this error:
error TS2345: Argument of type 'unknown' is not assignable to parameter of type 'DocumentReference'.
If I cast the AngularFirestoreDocument to a DocumentReference to any:
writer.update(<any> this.transCollection.doc(id),t);
it does compile, but I get a runtime error when I try go batch update docs this way:
Uncaught (in promise): FirebaseError: [code=invalid-argument]: Function WriteBatch.update() requires its first argument to be a DocumentReference, but it was: an object
FirebaseError: Function WriteBatch.update() requires its first argument to be a DocumentReference, but it was: an object
I was expecting the code to compile and successfully batch update Transaction docs.
OK, I figured out how to do this using this really helpful article that provides a lot of documentation that angularfire2 doesn't have itself:
Firestore Advanced Usage : angularfire - atomic writes
You can access the javascript API through angularfire2's firestore module and create a DocumentRef through that API, instead of using angularfire2's AngularFirestoreDocument type.
The working code looks like this:
export class FinancialService {
batch_update_trans(trans) {
let writer = this.afs.firestore.batch();
let transDoc = null;
for (let t of trans) {
transDoc = this.afs.firestore.doc(
'balance_sheets/'+this.balance_sheet_id+"/transactions/"+t.id);
writer.update(transDoc,t);
}
return writer.commit();
}
}

How to create an Aurelia-Validation Validation object for Jasmine tests

I'm currently using the Aurelia-Validation plugin to do client side validation. Since the validation object must be injected into the calling class's constructor, all my jasmine tests for the class in question now fail(since there's no validation object being passed in)
I've been trying to create a mock Validation object for a while now, or even a real one but i can't seem to get it right. The closest I've gotten is:
beforeEach(() => {
cache = new Cache();
session = new Session();
var valCon = new ValidationConfig();
var obsLoc = new ObserverLocator();
sut = new InsuredInformation(session, cache, new Validation(obsLoc,valCon));
});
But I keep getting errors when I run Karma saying:
TypeError: Expecting a function in instanceof check, but got [object Object]
I'm assuming this has something to do with the validation object and how i have instantiated it. Has anyone successfully created Jasmine tests for Aurelia View-Models that make use of the aurelia-validation plugin?
Try using the Container to instantiate your object. You may need to initialize the platform abstraction layer.
import {Container} from 'aurelia-framework'; // or 'aurelia-dependency-injection'
import {initialize as initializePAL} from 'aurelia-pal-browser'; // you may need to `jspm install aurelia-pal-browser`
initializePAL();
beforeEach(() => {
let container = new Container();
sut = container.get(InsuredInformation);
foo = container.get(SomeOtherClassThatYouWantToTest);
});

C# ElasticSeach Mock Suggestions

I am trying to mock a suggest response, however suggestionOption.Setup(x => x.Text).Returns("Hello") is throwing an exception:
An exception of type System.NotSupportedException occurred in
Moq.dll but was not handled in user code Additional information:
Invalid setup on a non-virtual (overridable in VB) member: x => x.Text
var searchSuggestResponseMock = new Mock<ISuggestResponse>();
var suggestionOption = new Mock<SuggestOption>();
suggestionOption.Setup(x => x.Text).Returns("Hello");
suggestionOption.Setup(x => x.Payload).Returns("{path:\"drugs/hello\"}");
var suggestion = new Mock<Suggest>();
suggestion.Setup(x => x.Options).Returns(new List<SuggestOption> { suggestionOption.Object });
searchSuggestResponseMock.Setup(x => x.Suggestions).Returns(new Dictionary<string, Suggest[]>()
{
{"suggest", new Suggest[] {suggestion.Object}},
});
var mock = new Mock<IConnector>();
mock.Setup(x => x.getClient()
.Suggest<Term>(Moq.It.IsAny<Func<SuggestDescriptor<Term>,
SuggestDescriptor<Term>>>())).Returns(searchSuggestResponseMock.Object);
_connector = mock.Object;
You can't mock non-virtual methods. As the error states:
Invalid setup on non-virtual member
Moq does its magic by acting as a proxy between your code and the real class. It does this by taking advantage of virtual methods. Without having a virtual method, Moq can't intercept the call.
Neither SuggestionOption, or Suggest are easily mockable, as they have non-virtual, internal set based properties, and do not implement any specific interface.
It looks like you are maybe mocking at too low a level. If you don't want to call Elastic to get your list of suggestions then have a method which just returns an array of strings (or your own custom Suggestion class) and mock that instead.
Or just call Elastic for real, as long as you are passing in sensible values which don't return thousands of suggestions.
(Or you could in theory create instances of Suggest, and set the internal properties via reflection, but this is not ideal obviously).

Flash embedding image from string parameter

I'm trying to embed an image in the constructor of my RangedItem class
public class RangedItem extends Item{
public var speed:Number;
public function RangedItem(s:Number, n:String, d:Number, path:String):void{
super(n, d);
speed = s;
[Embed(source=path, mimeType="image/png")] const IMAGE:Class;
}
}
Here is the code i'm using to construct the item
items.push(new RangedItem(item.speed, item.name, item.damage, '/img/gun.png'));
But I get these errors
col: 4: Error: unable to resolve 'path' for transcoding
col: 4: Error: Unable to transcode path.
img/gun.png exists for sure because if I replace path with "img/gun.png" everything works fine.
I'm using the flashpunk framework by the way if that changes anything.
What am I doing wrong?
Thanks in advance!
The [Embed] metadata, is used at compile time, not run time. So the variable interpolation that you're trying to do here with path won't work:
[Embed(source=path, mimeType="image/png")] const IMAGE:Class;
The compiler is expecting a literal string with the path to the image:
[Embed(source="path/to/my/image.png", mimeType="image/png")] const IMAGE:Class;
What you might consider doing is creating a Singleton (or your favorite pattern) class that contains all of your embedded images. Then your classes can refer to the assets in the singleton class and even pass references to them in the constructors of other classes.

Resources