VMware Cloud Community
yangjianus
Contributor
Contributor
Jump to solution

How to create vCACCAFEElementState instance

Hi,

I'm trying to change Blueprint from vRO workflow, I am able to change some part of the blueprint, such as description, size of input box size, etc.

When I am trying to hide a input, which set the VisibilityConstraint to true. Since JavaScript it pass by value. I have to create new vCACCAFEElementState with updated facets, then assign it to field.

field.initialStaticState = new vCACCAFEElementState(facets, initialStaticState.getDependencies());

Then I got the following error.

[2016-09-08 21:33:15.487] [E] Unable to create object : vCACCAFEElementState : Class ch.dunes.vso.sdk.DynamicWrapper can not access a member of class com.vmware.vcac.platform.content.facets.ElementState with modifiers "protected"

Anyone had experience with this?

Thanks

Reply
0 Kudos
1 Solution

Accepted Solutions
iiliev
VMware Employee
VMware Employee
Jump to solution

Hi,

vCACCAFEElementState scripting class is backed by a Java class com.vmware.vcac.platform.content.facets.ElementState which has 2 constructors - one argument-less, and one taking 2 arguments - java.util.Map and java.util.Set.

When you try to instantiate a new object of class vCACCAFEElementState in Javascript, the scripting engine tries to find an appropriate constructor for the corresponding Java class and then invokes it with the provided arguments. As Javascript and Java type systems are different, usually argument conversion is required. In your sample, the first argument need to be converted to java.util.Map, and the second argument need to be converted to java.util.Set.

Apparently, the type conversion code has some issues with converting to java.util.Set. As a result, the constructor with 2 arguments cannot be invoked, and as a backup variant the platform tries to invoke the argument-less constructor. Unfortunately, this constructor of ElementState is marked as protected/non-public, hence you gets the error 'can not access...'.

This looks like a bug to me. I'll open a PR to fix type conversion code to properly handle java.util.Set arguments.

View solution in original post

7 Replies
iiliev
VMware Employee
VMware Employee
Jump to solution

Hi,

vCACCAFEElementState scripting class is backed by a Java class com.vmware.vcac.platform.content.facets.ElementState which has 2 constructors - one argument-less, and one taking 2 arguments - java.util.Map and java.util.Set.

When you try to instantiate a new object of class vCACCAFEElementState in Javascript, the scripting engine tries to find an appropriate constructor for the corresponding Java class and then invokes it with the provided arguments. As Javascript and Java type systems are different, usually argument conversion is required. In your sample, the first argument need to be converted to java.util.Map, and the second argument need to be converted to java.util.Set.

Apparently, the type conversion code has some issues with converting to java.util.Set. As a result, the constructor with 2 arguments cannot be invoked, and as a backup variant the platform tries to invoke the argument-less constructor. Unfortunately, this constructor of ElementState is marked as protected/non-public, hence you gets the error 'can not access...'.

This looks like a bug to me. I'll open a PR to fix type conversion code to properly handle java.util.Set arguments.

yangjianus
Contributor
Contributor
Jump to solution

Thanks for your quick reply.

I am struggling on convert the facets array into java.util.Map, what's the right way to convert?

Reply
0 Kudos
yangjianus
Contributor
Contributor
Jump to solution

llian,

At this point, do you think there is any workaround for this? I guess the fix in your PR maybe included in next release, and that may not available any time soon.

I didn't write a vRO plugin before, just read some high level documentations. Do you think we could write a plugin for this, since plugin is Java. And there is a ElementStateBuilder which could create a ElementState instance.

Also can you point out the documentation where how the type conversion happen between Javascript and Java?

Thanks

Reply
0 Kudos
iiliev
VMware Employee
VMware Employee
Jump to solution

A workaround would be available if there is some other way to instantiate element state without using the constructor that requires java.util.Set argument. Or if there is no such way, the plug-in could be fixed to provide it; at any case, a new plug-in build can be released quicker than the next vRO release.

There is no documentation on how vRO implements Java <-> Javascript type conversions. I can point you to relevant parts of vRO source code if you have access to VMware internal network.

Here is some sample code showing how facets array can be converted to java.util.Map, as you asked in a previous comment. This is easy because vRO has a special scripting type Properties which is very similar to Java's map/hashtable

var facetsArray = [new vCACCAFEVisibilityConstraint(true), new vCACCAFEUniqueConstraint(true)]; // this is a sample array with 2 facets

var facetsMap = new Properties(); // this would be the result facets map

for each (var facet in facetsArray) {

  facetsMap.put(facet.getClass(), facet); // here, facet class is used as an index in the map, but if needed they can be indexed with something else

}

yangjianus
Contributor
Contributor
Jump to solution

I will try to do this in a plugin. I don't have access to Vmware internal network.

Thanks for the quick reply and the nice sample code.

Reply
0 Kudos
yangjianus
Contributor
Contributor
Jump to solution

llian,

I created a plugin which accept facets and dependencies, and return a new ElementState.

@VsoObject(singleton = true)

public class UBWorkaround {

  public static final String TYPE = "UBWorkaround";

  @Autowired

  private UBWorkaroundService service;

  public UBWorkaround() {

  }

  public static UBWorkaround createScriptingSingleton(IPluginFactory factory) {

  return ((AbstractSpringPluginFactory) factory).createScriptingObject(UBWorkaround.class);

  }

  @VsoMethod(vsoReturnType = "vCACCAFEElementState")

  public ElementState newElementState(Map<Class<? extends Constraint>, Constraint> facets, String[] dependencies) {

  return service.newElementState(facets, dependencies);

  }

}

After I installed the plugin, I'm able to create new vCACCAFEElementState instance, and assign it back to field.initialStaticState. But when I do the update it failed.

I compared the original field.initialStaticState, and the one create by plugin. They're different in the facets collection.


Original initialStaticState:

DynamicWrapper (Instance) : [vCACCAFEElementState]-[class com.vmware.vcac.platform.content.facets.ElementState] -- VALUE : ElementState[facets=FacetCollection[[VisibilityConstraint[com.vmware.vcac.platform.content.criteria.ConstantClause@4ee]]], dependencies=[]]


New initialStaticState:

DynamicWrapper (Instance) : [vCACCAFEElementState]-[class com.vmware.vcac.platform.content.facets.ElementState] -- VALUE : ElementState[facets=FacetCollection[[ch.dunes.vso.sdk.DynamicWrapper@47605f1c / DynamicWrapper (Instance) : [vCACCAFEVisibilityConstraint]-[class com.vmware.vcac.platform.content.facets.VisibilityConstraint] -- VALUE : VisibilityConstraint[com.vmware.vcac.platform.content.criteria.ConstantClause@4ee]]], dependencies=[]]



Looks like the one I created, is having additional DynamicWrapper on the vCACCAFEVisibilityConstraint.


Do you have any idea what I did wrong?

Reply
0 Kudos
yangjianus
Contributor
Contributor
Jump to solution

It turns out if I create the instance in Java, it will print out the same.

Finally I have changed to pass the whole blueprint object to the plugin, updated it, then return to vRO workflow. Then the update works as expected.

* The field I'm updating is NOT initialStaticState, it is state.

Reply
0 Kudos