brooklyn-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Aled Sage (JIRA)" <j...@apache.org>
Subject [jira] [Created] (BROOKLYN-448) Support java 8 lambdas as config key values
Date Mon, 06 Mar 2017 18:03:32 GMT
Aled Sage created BROOKLYN-448:
----------------------------------

             Summary: Support java 8 lambdas as config key values
                 Key: BROOKLYN-448
                 URL: https://issues.apache.org/jira/browse/BROOKLYN-448
             Project: Brooklyn
          Issue Type: Improvement
    Affects Versions: 0.10.0
            Reporter: Aled Sage
            Priority: Minor


It would be nice if users could write Java 8 lambda expressions, and use these as config values
when writing/using Java-based entities.

However, the persistence (via xstream version 1.4.8) does not work correctly for it.

According to http://x-stream.github.io/jira/767/, xstream could not support lambdas in 1.4.7
but this was fixed in 1.4.8 (i.e. fixed in the version we *are* using). I haven't investigated
further as to why it's not serializing as we'd expect.

Below is the persisted state file that was written by my test entity. Note the "predicate"
config value is null.

{noformat}
<entity>
  <brooklynVersion>0.11.0-SNAPSHOT</brooklynVersion>
  <type>org.apache.brooklyn.core.test.entity.TestEntityImpl</type>
  <id>urqjprgoso</id>
  <displayName>TestEntity:urqj</displayName>
  <parent>fy4mk95jwr</parent>
  <config>
    <predicate>
      <null/>
    </predicate>
  </config>
  <attributes>
    <entity.id>urqjprgoso</entity.id>
    <application.id>fy4mk95jwr</application.id>
    <catalog.id>
      <null/>
    </catalog.id>
  </attributes>
  <enrichers>
    <string>sgpovb54t4</string>
    <string>p4blzr6krc</string>
  </enrichers>
  <configKeys>
    <predicate>
      <configKey>
        <name>predicate</name>
        <typeToken class="com.google.common.reflect.TypeToken$SimpleTypeToken">
          <runtimeType class="com.google.common.reflect.Types$ParameterizedTypeImpl">
            <argumentsList>
              <com.google.common.reflect.Types_-WildcardTypeImpl>
                <lowerBounds>
                  <java-class>java.lang.String</java-class>
                </lowerBounds>
                <upperBounds>
                  <java-class>java.lang.Object</java-class>
                </upperBounds>
              </com.google.common.reflect.Types_-WildcardTypeImpl>
            </argumentsList>
            <rawType>java.util.function.Predicate</rawType>
          </runtimeType>
        </typeToken>
        <description>predicate</description>
        <reconfigurable>false</reconfigurable>
        <constraint class="com.google.common.base.Predicates$ObjectPredicate">ALWAYS_TRUE</constraint>
      </configKey>
    </predicate>
  </configKeys>
</entity>
{noformat}


Below is my Java 8 test to illustrate this: {{testLambdaConfigValue}} fails because the retrieved
config key value is null after rebind. For comparison, the tests {{testAnonymousInnerClassConfigValue}}
and {{testNonStaticInnerClassConfigValue}} fail at rebind-time with {{ConversionException:
Could not call java.security.CodeSource.readObject() : null}}.

{noformat}
public class LambdaConfigTest extends RebindTestFixtureWithApp {

	@SuppressWarnings("serial")
	public static final ConfigKey<Predicate<? super String>> PREDICATE = ConfigKeys.newConfigKey(
			new TypeToken<Predicate<? super String>>() {},
			"predicate");

	@Test
	public void testLambdaConfigValue() throws Exception {
		Predicate<? super String> val = p -> p.startsWith("val");
		runPredicateConfigValue(val);
	}

	// Assumes the predicate matches "val1", but not "different1"
	protected void runPredicateConfigValue(Predicate<? super String> val) throws Exception
{
		Entity entity = app().addChild(EntitySpec.create(TestEntity.class)
				.configure(PREDICATE, val));
		
		List<String> all = ImmutableList.of("val1", "different1");
		List<String> expectedFiltered = ImmutableList.of("val1");
		List<String> filtered = filter(all, entity.config().get(PREDICATE));
		assertEquals(filtered, expectedFiltered);
		
		rebind();
		
		Entity newEntity = Iterables.getOnlyElement(app().getChildren());
		assertNotNull(newEntity.config().get(PREDICATE));
		List<String> newFiltered = filter(all, newEntity.config().get(PREDICATE));
		assertEquals(newFiltered, expectedFiltered);
	}

	private List<String> filter(List<String> vals, Predicate<? super String>
tester) {
		List<String> result = Lists.newArrayList();
		for (String val : vals) {
			if (tester.test(val)) {
				result.add(val);
			}
		}
		return result;
	}
	
	@Test
	public void testAnonymousInnerClassConfigValue() throws Exception {
		Predicate<? super String> val = new Predicate<String>() {
			@Override public boolean test(String input) {
				return input.startsWith("val");
			}
		};
		runPredicateConfigValue(val);
	}

	@Test
	public void testNonStaticInnerClassConfigValue() throws Exception {
		class MyNontStaticPredicate implements Predicate<String> {
			@Override public boolean test(String input) {
				return input.startsWith("val");
			}
		}
		runPredicateConfigValue(new MyNontStaticPredicate());
	}

	@Test
	public void testStaticInnerClassConfigValue() throws Exception {
		runPredicateConfigValue(new MyStaticPredicate());
	}
	
	static class MyStaticPredicate implements Predicate<String> {
		@Override public boolean test(String input) {
			return input.startsWith("val");
		}
	}
}
{noformat}




--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Mime
View raw message