From 3c1a7805add0dd584a26b1a0174d8ced44b5c014 Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Wed, 3 May 2017 20:43:23 +0100 Subject: [PATCH 1/4] Delete brooklyn-storage-hazelcast This has not been documented, used or recommended ever! It was more experimental, as an approach that might have replaced the existing persisted state approach but never did. --- .../deserializingClassRenames.properties | 4 - pom.xml | 2 - storage/hazelcast/pom.xml | 88 -------------- .../storage/impl/hazelcast/EntityId.java | 36 ------ .../hazelcast/EntityStreamSerializer.java | 68 ----------- .../impl/hazelcast/HazelcastDataGrid.java | 89 --------------- .../hazelcast/HazelcastDataGridFactory.java | 42 ------- .../impl/hazelcast/HazelcastStorageTest.java | 107 ------------------ 8 files changed, 436 deletions(-) delete mode 100644 storage/hazelcast/pom.xml delete mode 100644 storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityId.java delete mode 100644 storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityStreamSerializer.java delete mode 100644 storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java delete mode 100644 storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java delete mode 100644 storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java diff --git a/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties b/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties index 992d9e5ce2..8a6a7a49d2 100644 --- a/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties +++ b/core/src/main/resources/org/apache/brooklyn/core/mgmt/persist/deserializingClassRenames.properties @@ -1103,10 +1103,6 @@ brooklyn.entity.webapp.tomcat.TomcatDriver brooklyn.entity.webapp.tomcat.TomcatServer : org.apache.brooklyn.entity.webapp.tomcat.TomcatServer brooklyn.entity.webapp.tomcat.TomcatServerImpl : org.apache.brooklyn.entity.webapp.tomcat.TomcatServerImpl brooklyn.entity.webapp.tomcat.TomcatSshDriver : org.apache.brooklyn.entity.webapp.tomcat.TomcatSshDriver -brooklyn.internal.storage.impl.hazelcast.EntityId : org.apache.brooklyn.internal.storage.impl.hazelcast.EntityId -brooklyn.internal.storage.impl.hazelcast.EntityStreamSerializer : org.apache.brooklyn.internal.storage.impl.hazelcast.EntityStreamSerializer -brooklyn.internal.storage.impl.hazelcast.HazelcastDataGrid : org.apache.brooklyn.internal.storage.impl.hazelcast.HazelcastDataGrid -brooklyn.internal.storage.impl.hazelcast.HazelcastDataGridFactory : org.apache.brooklyn.internal.storage.impl.hazelcast.HazelcastDataGridFactory io.brooklyn.camp.brooklyn.BrooklynCampConstants : org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants io.brooklyn.camp.brooklyn.BrooklynCampPlatform : org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform io.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract : org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract diff --git a/pom.xml b/pom.xml index d2809f3952..450e154ed3 100644 --- a/pom.xml +++ b/pom.xml @@ -221,8 +221,6 @@ software/base software/winrm - storage/hazelcast - server-cli launcher-common launcher diff --git a/storage/hazelcast/pom.xml b/storage/hazelcast/pom.xml deleted file mode 100644 index 1017f3c44e..0000000000 --- a/storage/hazelcast/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - 4.0.0 - brooklyn-storage-hazelcast - jar - Brooklyn Hazelcast Storage - - Provides a Hazelcast implementation of Storage - - - - org.apache.brooklyn - brooklyn-parent - 0.12.0-SNAPSHOT - ../../parent/pom.xml - - - - 3.5.4 - - - - - org.apache.brooklyn - brooklyn-core - ${project.version} - - - org.apache.brooklyn - brooklyn-utils-common - ${project.version} - - - org.apache.brooklyn - brooklyn-api - ${project.version} - - - com.google.guava - guava - - - - com.hazelcast - hazelcast - ${hazelcast.version} - - - - - org.testng - testng - test - - - org.apache.brooklyn - brooklyn-test-support - ${project.version} - test - - - - - diff --git a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityId.java b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityId.java deleted file mode 100644 index db7f283efb..0000000000 --- a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityId.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.internal.storage.impl.hazelcast; - -import java.io.Serializable; - -class EntityId implements Serializable { - - private static final long serialVersionUID = 1L; - - private final String id; - - EntityId(String id) { - this.id = id; - } - - String getId() { - return id; - } -} diff --git a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityStreamSerializer.java b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityStreamSerializer.java deleted file mode 100644 index 5cea12bb9f..0000000000 --- a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/EntityStreamSerializer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.internal.storage.impl.hazelcast; - -import com.hazelcast.nio.ObjectDataInput; -import com.hazelcast.nio.ObjectDataOutput; -import com.hazelcast.nio.serialization.StreamSerializer; - -import java.io.IOException; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.core.objs.proxy.EntityProxyImpl; - -import static java.lang.String.format; - -class EntityStreamSerializer implements StreamSerializer { - - private HazelcastDataGrid hazelcastDataGrid; - - public EntityStreamSerializer(HazelcastDataGrid hazelcastDataGrid) { - this.hazelcastDataGrid = hazelcastDataGrid; - } - - @Override - public Object read(ObjectDataInput in) throws IOException { - EntityId id = in.readObject(); - Entity entity = hazelcastDataGrid.getManagementContext().getEntityManager().getEntity(id.getId()); - if (entity == null) { - throw new IllegalStateException(format("Entity with id [%s] is not found", id)); - } - return java.lang.reflect.Proxy.newProxyInstance( - entity.getClass().getClassLoader(), - entity.getClass().getInterfaces(), - new EntityProxyImpl(entity)); - } - - @Override - public void write(ObjectDataOutput out, Object object) throws IOException { - Entity entity = (Entity) object; - out.writeObject(new EntityId(entity.getId())); - } - - @Override - public int getTypeId() { - return 5000; - } - - @Override - public void destroy() { - //no-op - } -} diff --git a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java deleted file mode 100644 index 0219f107bd..0000000000 --- a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.internal.storage.impl.hazelcast; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.core.internal.storage.DataGrid; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; - -import com.google.common.collect.ImmutableMap; -import com.hazelcast.config.Config; -import com.hazelcast.config.SerializerConfig; -import com.hazelcast.core.Hazelcast; -import com.hazelcast.core.HazelcastInstance; -import com.hazelcast.core.HazelcastInstanceNotActiveException; - -public class HazelcastDataGrid implements DataGrid { - - private final HazelcastInstance hz; - private final ManagementContextInternal managementContext; - - public HazelcastDataGrid(ManagementContextInternal managementContext, HazelcastInstance hazelcastInstance) { - this.managementContext = managementContext; - if (hazelcastInstance == null) { - Config config = new Config(); - SerializerConfig entitySerializeConfig = new SerializerConfig(); - entitySerializeConfig.setTypeClassName(Entity.class.getName()); - entitySerializeConfig.setImplementation(new EntityStreamSerializer(this)); - config.getSerializationConfig().addSerializerConfig(entitySerializeConfig); - this.hz = Hazelcast.newHazelcastInstance(config); - } else { - this.hz = hazelcastInstance; - } - } - - public ManagementContextInternal getManagementContext() { - return managementContext; - } - - @Override - public ConcurrentMap getMap(String id) { - return hz.getMap(id); - } - - @Override - public void remove(String id) { - hz.getMap(id).destroy(); - } - - @Override - public void terminate() { - try { - hz.getLifecycleService().shutdown(); - } catch (HazelcastInstanceNotActiveException ignore) { - } - } - - @Override - public Map getDatagridMetrics() { - // TODO would like to have better metrics - return ImmutableMap.of("name", hz.getName(), "isRunning", hz.getLifecycleService().isRunning()); - } - - @Override - public Set getKeys() { - // TODO would like to have all known keys (for tests) - return Collections.emptySet(); - } -} diff --git a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java deleted file mode 100644 index fa15fc7d1f..0000000000 --- a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.internal.storage.impl.hazelcast; - -import org.apache.brooklyn.core.internal.storage.DataGrid; -import org.apache.brooklyn.core.internal.storage.DataGridFactory; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; - -import com.hazelcast.core.HazelcastInstance; - -public class HazelcastDataGridFactory implements DataGridFactory { - - private HazelcastInstance hazelcastInstance; - - public HazelcastDataGridFactory() { - } - - public HazelcastDataGridFactory(HazelcastInstance hazelcastInstance) { - this.hazelcastInstance = hazelcastInstance; - } - - @Override - public DataGrid newDataGrid(ManagementContextInternal managementContext) { - return new HazelcastDataGrid(managementContext,hazelcastInstance); - } -} \ No newline at end of file diff --git a/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java b/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java deleted file mode 100644 index 4c43e1c396..0000000000 --- a/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.storage.impl.hazelcast; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -import java.util.List; -import java.util.Map; - -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; -import org.apache.brooklyn.core.internal.BrooklynProperties; -import org.apache.brooklyn.core.internal.storage.BrooklynStorage; -import org.apache.brooklyn.core.internal.storage.DataGridFactory; -import org.apache.brooklyn.core.internal.storage.Reference; -import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; -import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; -import org.apache.brooklyn.internal.storage.impl.hazelcast.HazelcastDataGrid; -import org.apache.brooklyn.internal.storage.impl.hazelcast.HazelcastDataGridFactory; -import org.apache.brooklyn.util.collections.MutableList; - -import com.hazelcast.core.Hazelcast; - -@Test(groups="Integration") -public class HazelcastStorageTest { - - private LocalManagementContext managementContext; - private BrooklynStorage storage; - - @BeforeMethod(alwaysRun = true) - public void setUp() { - BrooklynProperties properties = BrooklynProperties.Factory.newDefault(); - properties.put(DataGridFactory.class.getName(), HazelcastDataGridFactory.class.getName()); - managementContext = new LocalManagementContext(properties); - storage = managementContext.getStorage(); - } - - @AfterMethod(alwaysRun = true) - public void tearDown() { - if (managementContext != null) managementContext.terminate(); - Hazelcast.shutdownAll(); - } - - //test to verify that our HazelcastDatagrid really is being picked up. - @Test - public void testPickUp(){ - assertTrue(storage instanceof BrooklynStorageImpl,"storage should be instance of BrooklynStorageImpl"); - BrooklynStorageImpl brooklynStorageImpl = (BrooklynStorageImpl)storage; - assertTrue(brooklynStorageImpl.getDataGrid() instanceof HazelcastDataGrid,"storage should be instanceof HazelcastDataGrid"); - } - - @Test - public void testGetMap() { - Map map = storage.getMap("somemap"); - map.put("foo", "bar"); - assertEquals( map.get("foo"),"bar"); - } - - @Test - public void testGetReference() { - Reference ref = storage.getReference("someReference"); - ref.set("bar"); - assertEquals(ref.get(), "bar"); - } - - @Test - public void testNonConcurrentList(){ - Reference> ref = storage.getNonConcurrentList("someReference"); - ref.set(MutableList.of("bar")); - - assertEquals(ref.get().get(0),"bar"); - } - - @Test - public void testRemoveReference(){ - Reference ref = storage.getReference("someReference"); - ref.set("bar"); - storage.remove("someReference"); - assertEquals(ref.get(), null); - } - - @Test - public void testRemoveMap(){ - Map map = storage.getMap("somemap"); - map.put("foo", "bar"); - storage.remove("somemap"); - assertEquals(null, map.get("foo")); - } -} From 236afd7ab95a27e3a74fd28dc0337250c880ec32 Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Wed, 3 May 2017 20:53:42 +0100 Subject: [PATCH 2/4] ManagementContext.dataGrid not configurable --- .../internal/AbstractManagementContext.java | 48 ++----------------- .../mgmt/internal/LocalManagementContext.java | 28 +++-------- 2 files changed, 9 insertions(+), 67 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java index eed121d0f7..193f328b7d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java @@ -19,7 +19,6 @@ package org.apache.brooklyn.core.mgmt.internal; import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; import static org.apache.brooklyn.core.catalog.internal.CatalogUtils.newClassLoadingContextForCatalogItems; import java.net.URI; @@ -61,8 +60,6 @@ import org.apache.brooklyn.core.entity.drivers.downloads.BasicDownloadsManager; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.internal.storage.BrooklynStorage; -import org.apache.brooklyn.core.internal.storage.DataGrid; -import org.apache.brooklyn.core.internal.storage.DataGridFactory; import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; import org.apache.brooklyn.core.internal.storage.impl.inmemory.InMemoryDataGridFactory; import org.apache.brooklyn.core.location.BasicLocationRegistry; @@ -75,7 +72,6 @@ import org.apache.brooklyn.core.typereg.BasicBrooklynTypeRegistry; import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.task.BasicExecutionContext; @@ -95,36 +91,6 @@ public abstract class AbstractManagementContext implements ManagementContextInternal { private static final Logger log = LoggerFactory.getLogger(AbstractManagementContext.class); - private static DataGridFactory loadDataGridFactory(BrooklynProperties properties) { - String clazzName = properties.getFirst(DataGridFactory.class.getName()); - if(clazzName == null){ - clazzName = InMemoryDataGridFactory.class.getName(); - } - - Class clazz; - try{ - //todo: which classloader should we use? - clazz = new ClassLoaderUtils(AbstractManagementContext.class).loadClass(clazzName); - }catch(ClassNotFoundException e){ - throw new IllegalStateException(format("Could not load class [%s]",clazzName),e); - } - - Object instance; - try { - instance = clazz.newInstance(); - } catch (InstantiationException e) { - throw new IllegalStateException(format("Could not instantiate class [%s]",clazzName),e); - } catch (IllegalAccessException e) { - throw new IllegalStateException(format("Could not instantiate class [%s]",clazzName),e); - } - - if(!(instance instanceof DataGridFactory)){ - throw new IllegalStateException(format("Class [%s] not an instantiate of class [%s]",clazzName, DataGridFactory.class.getName())); - } - - return (DataGridFactory)instance; - } - static { ResourceUtils.addClassLoaderProvider(new Function() { @Override @@ -194,24 +160,16 @@ public BrooklynClassLoadingContext apply(@Nullable Object input) { protected Maybe uri = Maybe.absent(); protected CatalogInitialization catalogInitialization; - public AbstractManagementContext(BrooklynProperties brooklynProperties){ - this(brooklynProperties, null); - } - - public AbstractManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) { + public AbstractManagementContext(BrooklynProperties brooklynProperties) { this.configMap = new DeferredBrooklynProperties(brooklynProperties, this); this.scratchpad = new BasicScratchpad(); this.entityDriverManager = new BasicEntityDriverManager(); this.downloadsManager = BasicDownloadsManager.newDefault(configMap); - if (datagridFactory == null) { - datagridFactory = loadDataGridFactory(brooklynProperties); - } - DataGrid datagrid = datagridFactory.newDataGrid(this); - + this.catalog = new BasicBrooklynCatalog(this); this.typeRegistry = new BasicBrooklynTypeRegistry(this); - this.storage = new BrooklynStorageImpl(datagrid); + this.storage = new BrooklynStorageImpl(new InMemoryDataGridFactory().newDataGrid(this)); this.rebindManager = new RebindManagerImpl(this); // TODO leaking "this" reference; yuck this.highAvailabilityManager = new HighAvailabilityManagerImpl(this); // TODO leaking "this" reference; yuck diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java index bdb6302cd8..3e3b77606d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java @@ -49,7 +49,6 @@ import org.apache.brooklyn.core.internal.BrooklynInitialization; import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.internal.BrooklynProperties.Factory.Builder; -import org.apache.brooklyn.core.internal.storage.DataGridFactory; import org.apache.brooklyn.core.mgmt.entitlement.Entitlements; import org.apache.brooklyn.core.mgmt.ha.OsgiManager; import org.apache.brooklyn.core.objs.proxy.InternalEntityFactory; @@ -150,41 +149,26 @@ public LocalManagementContext() { this(BrooklynProperties.Factory.builderDefault()); } - public LocalManagementContext(BrooklynProperties brooklynProperties) { - this(brooklynProperties, (DataGridFactory)null); - } - /** * Creates a new LocalManagementContext. * * @param brooklynProperties the BrooklynProperties. - * @param datagridFactory the DataGridFactory to use. If this instance is null, it means that the system - * is going to use BrooklynProperties to figure out which instance to load or otherwise - * use a default instance. */ @VisibleForTesting - public LocalManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) { - this(Builder.fromProperties(brooklynProperties), datagridFactory); + public LocalManagementContext(BrooklynProperties brooklynProperties) { + this(Builder.fromProperties(brooklynProperties)); } public LocalManagementContext(Builder builder) { - this(builder, null, null); - } - - public LocalManagementContext(Builder builder, DataGridFactory datagridFactory) { - this(builder, null, datagridFactory); - } - - public LocalManagementContext(Builder builder, Map brooklynAdditionalProperties) { - this(builder, brooklynAdditionalProperties, null); + this(builder, null); } public LocalManagementContext(BrooklynProperties brooklynProperties, Map brooklynAdditionalProperties) { - this(Builder.fromProperties(brooklynProperties), brooklynAdditionalProperties, null); + this(Builder.fromProperties(brooklynProperties), brooklynAdditionalProperties); } - public LocalManagementContext(Builder builder, Map brooklynAdditionalProperties, DataGridFactory datagridFactory) { - super(builder.build(), datagridFactory); + public LocalManagementContext(Builder builder, Map brooklynAdditionalProperties) { + super(builder.build()); checkNotNull(configMap, "brooklynProperties"); From 21c40ba0b9ab2eabe76ce834117964a1613a4677 Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Wed, 3 May 2017 20:59:47 +0100 Subject: [PATCH 3/4] Delete DataGridFactory --- .../internal/storage/DataGridFactory.java | 38 ------------------ .../inmemory/InMemoryDataGridFactory.java | 40 ------------------- .../internal/AbstractManagementContext.java | 4 +- 3 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGridFactory.java delete mode 100644 core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InMemoryDataGridFactory.java diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGridFactory.java b/core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGridFactory.java deleted file mode 100644 index 45c696bbcf..0000000000 --- a/core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGridFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.core.internal.storage; - -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; - -/** - * A factory for creating a {@link DataGrid}. - * - * Implementations of this interface should have a public no arg constructor; this constructor will be - * called through reflection in the {@link org.apache.brooklyn.core.mgmt.internal.LocalManagementContext}. - */ -public interface DataGridFactory { - - /** - * Creates a {@link BrooklynStorage} instance. - * - * @param managementContext the ManagementContextInternal - * @return the created BrooklynStorage. - */ - DataGrid newDataGrid(ManagementContextInternal managementContext); -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InMemoryDataGridFactory.java b/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InMemoryDataGridFactory.java deleted file mode 100644 index 0ce0aa75c0..0000000000 --- a/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InMemoryDataGridFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.core.internal.storage.impl.inmemory; - -import org.apache.brooklyn.core.internal.storage.DataGrid; -import org.apache.brooklyn.core.internal.storage.DataGridFactory; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; - -public class InMemoryDataGridFactory implements DataGridFactory { - - public static DataGridFactory ofInstance(final DataGrid datagrid) { - return new DataGridFactory() { - @Override - public DataGrid newDataGrid(ManagementContextInternal managementContext) { - return datagrid; - } - }; - } - - @Override - public DataGrid newDataGrid(ManagementContextInternal managementContext) { - return new InmemoryDatagrid(); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java index 193f328b7d..45a45d7ada 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java @@ -61,7 +61,7 @@ import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.internal.storage.BrooklynStorage; import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; -import org.apache.brooklyn.core.internal.storage.impl.inmemory.InMemoryDataGridFactory; +import org.apache.brooklyn.core.internal.storage.impl.inmemory.InmemoryDatagrid; import org.apache.brooklyn.core.location.BasicLocationRegistry; import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential; @@ -169,7 +169,7 @@ public AbstractManagementContext(BrooklynProperties brooklynProperties) { this.catalog = new BasicBrooklynCatalog(this); this.typeRegistry = new BasicBrooklynTypeRegistry(this); - this.storage = new BrooklynStorageImpl(new InMemoryDataGridFactory().newDataGrid(this)); + this.storage = new BrooklynStorageImpl(new InmemoryDatagrid()); this.rebindManager = new RebindManagerImpl(this); // TODO leaking "this" reference; yuck this.highAvailabilityManager = new HighAvailabilityManagerImpl(this); // TODO leaking "this" reference; yuck From 6b59fcb6a0c8e57dcdd00b8c95ea2b410c8fcf2d Mon Sep 17 00:00:00 2001 From: Aled Sage Date: Thu, 4 May 2017 11:40:03 +0100 Subject: [PATCH 4/4] Hide DataGrid inside BrooklynStorageImpl --- .../core/internal/storage/DataGrid.java | 52 ------------------- .../storage/impl/BrooklynStorageImpl.java | 18 ++----- .../impl/{inmemory => }/InmemoryDatagrid.java | 11 +--- .../internal/AbstractManagementContext.java | 3 +- .../storage/impl/BrooklynStorageImplTest.java | 6 +-- .../longevity/EntityCleanupLongevityTest.java | 2 +- .../EntityCleanupLongevityTestFixture.java | 48 ++++++++++------- 7 files changed, 36 insertions(+), 104 deletions(-) delete mode 100644 core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGrid.java rename core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/{inmemory => }/InmemoryDatagrid.java (91%) diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGrid.java b/core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGrid.java deleted file mode 100644 index 09f50fb811..0000000000 --- a/core/src/main/java/org/apache/brooklyn/core/internal/storage/DataGrid.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.core.internal.storage; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentMap; - -import com.google.common.annotations.VisibleForTesting; - -public interface DataGrid { - - /** - * If a map already exists with this id, returns it; otherwise creates a new map stored - * in the datagrid. - */ - ConcurrentMap getMap(String id); - - /** - * Deletes the map for this id, if it exists; otherwise a no-op. - */ - void remove(String id); - - /** - * Terminates the DataGrid. If there is a real datagrid with multiple machines running, it doesn't mean that the - * datagrid is going to be terminated; it only means that all local resources of the datagrid are released. - */ - void terminate(); - - Map getDatagridMetrics(); - - /** Returns snapshot of known keys at this datagrid */ - @VisibleForTesting - Set getKeys(); - -} diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImpl.java b/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImpl.java index 60a1e7e246..5436b15c30 100644 --- a/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImpl.java @@ -25,40 +25,28 @@ import java.util.concurrent.ConcurrentMap; import org.apache.brooklyn.core.internal.storage.BrooklynStorage; -import org.apache.brooklyn.core.internal.storage.DataGrid; import org.apache.brooklyn.core.internal.storage.Reference; -import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; public class BrooklynStorageImpl implements BrooklynStorage { - private final DataGrid datagrid; + private final InmemoryDatagrid datagrid; private final ConcurrentMap refsMap; private final ConcurrentMap listsMap; private final ConcurrentMap>> refsCache; private final ConcurrentMap>> listRefsCache; - public BrooklynStorageImpl(DataGrid datagrid) { - this.datagrid = datagrid; + public BrooklynStorageImpl() { + this.datagrid = new InmemoryDatagrid(); this.refsMap = datagrid.getMap("refs"); this.listsMap = datagrid.getMap("lists"); this.refsCache = Maps.newConcurrentMap(); this.listRefsCache = Maps.newConcurrentMap(); } - /** - * Returns the DataGrid used by this BrooklynStorageImpl - * - * @return the DataGrid. - */ - @VisibleForTesting - public DataGrid getDataGrid() { - return datagrid; - } - @Override public Reference getReference(final String id) { // Can use different ref instances; no need to always return same one. Caching is an diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InmemoryDatagrid.java b/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/InmemoryDatagrid.java similarity index 91% rename from core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InmemoryDatagrid.java rename to core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/InmemoryDatagrid.java index 48600d9359..a63fa3d84f 100644 --- a/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/inmemory/InmemoryDatagrid.java +++ b/core/src/main/java/org/apache/brooklyn/core/internal/storage/impl/InmemoryDatagrid.java @@ -16,14 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.brooklyn.core.internal.storage.impl.inmemory; +package org.apache.brooklyn.core.internal.storage.impl; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.brooklyn.core.internal.storage.DataGrid; import org.apache.brooklyn.core.internal.storage.impl.ConcurrentMapAcceptingNullVals; import com.google.common.collect.ImmutableMap; @@ -34,13 +33,12 @@ * * @author aled */ -public class InmemoryDatagrid implements DataGrid { +class InmemoryDatagrid { private final Map> maps = Maps.newLinkedHashMap(); private final AtomicInteger creationCounter = new AtomicInteger(); @SuppressWarnings("unchecked") - @Override public ConcurrentMap getMap(String id) { synchronized (maps) { ConcurrentMap result = (ConcurrentMap) maps.get(id); @@ -64,30 +62,25 @@ private ConcurrentMap newMap() { return new ConcurrentMapAcceptingNullVals(Maps.newConcurrentMap()); } - @Override public void remove(String id) { synchronized (maps) { maps.remove(id); } } - @Override public void terminate() { synchronized (maps) { maps.clear(); } } - @Override public Map getDatagridMetrics() { synchronized (maps) { return ImmutableMap.of("size", maps.size(), "createCount", creationCounter.get()); } } - @Override public Set getKeys() { return maps.keySet(); } - } diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java index 45a45d7ada..c009437128 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java @@ -61,7 +61,6 @@ import org.apache.brooklyn.core.internal.BrooklynProperties; import org.apache.brooklyn.core.internal.storage.BrooklynStorage; import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; -import org.apache.brooklyn.core.internal.storage.impl.inmemory.InmemoryDatagrid; import org.apache.brooklyn.core.location.BasicLocationRegistry; import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential; @@ -169,7 +168,7 @@ public AbstractManagementContext(BrooklynProperties brooklynProperties) { this.catalog = new BasicBrooklynCatalog(this); this.typeRegistry = new BasicBrooklynTypeRegistry(this); - this.storage = new BrooklynStorageImpl(new InmemoryDatagrid()); + this.storage = new BrooklynStorageImpl(); this.rebindManager = new RebindManagerImpl(this); // TODO leaking "this" reference; yuck this.highAvailabilityManager = new HighAvailabilityManagerImpl(this); // TODO leaking "this" reference; yuck diff --git a/core/src/test/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImplTest.java b/core/src/test/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImplTest.java index 9dc02c5765..c90a206c35 100644 --- a/core/src/test/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImplTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/internal/storage/impl/BrooklynStorageImplTest.java @@ -29,10 +29,8 @@ import java.util.Map; import org.apache.brooklyn.core.internal.storage.BrooklynStorage; -import org.apache.brooklyn.core.internal.storage.DataGrid; import org.apache.brooklyn.core.internal.storage.Reference; import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; -import org.apache.brooklyn.core.internal.storage.impl.inmemory.InmemoryDatagrid; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -43,15 +41,13 @@ public class BrooklynStorageImplTest { - private DataGrid datagrid; private BrooklynStorage storage; @BeforeMethod(alwaysRun=true) public void setUp() throws Exception { // TODO Note that InmemoryDatagrid's ConcurrentMap currently returns snapshot for entrySet() and values() // so the tests here aren't particularly good for confirming it'll work against a real datagrid... - datagrid = new InmemoryDatagrid(); - storage = new BrooklynStorageImpl(datagrid); + storage = new BrooklynStorageImpl(); } @Test diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java index 26a45fa316..bdc56cf082 100644 --- a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTest.java @@ -53,7 +53,7 @@ public void testLocationCreatedAndUnmanaged() throws Exception { doTestManyTimesAndAssertNoMemoryLeak(JavaClassNames.niceClassAndMethod(), new Runnable() { @Override public void run() { - loc = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class)); + loc = newLoc(); managementContext.getLocationManager().unmanage(loc); } }); diff --git a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java index 8eeb29ece5..e8544d8494 100644 --- a/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java +++ b/core/src/test/java/org/apache/brooklyn/core/test/qa/longevity/EntityCleanupLongevityTestFixture.java @@ -18,7 +18,9 @@ */ package org.apache.brooklyn.core.test.qa.longevity; -import java.util.Set; +import static org.testng.Assert.assertTrue; + +import java.util.WeakHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; @@ -29,8 +31,6 @@ import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.entity.factory.ApplicationBuilder; import org.apache.brooklyn.core.internal.storage.BrooklynStorage; -import org.apache.brooklyn.core.internal.storage.DataGrid; -import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; import org.apache.brooklyn.core.location.SimulatedLocation; import org.apache.brooklyn.core.mgmt.internal.AbstractManagementContext; import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; @@ -50,6 +50,7 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; public abstract class EntityCleanupLongevityTestFixture { @@ -59,6 +60,9 @@ public abstract class EntityCleanupLongevityTestFixture { protected SimulatedLocation loc; protected TestApplication app; + protected WeakHashMap weakApps; + protected WeakHashMap weakLocs; + // since GC is not definitive (would that it were!) final static long MEMORY_MARGIN_OF_ERROR = 10*1024*1024; @@ -76,6 +80,9 @@ public void setUp() { // do this to ensure GC is initialized managementContext.getExecutionManager(); + + weakApps = new WeakHashMap<>(); + weakLocs = new WeakHashMap<>(); } @AfterMethod(alwaysRun=true) @@ -98,7 +105,8 @@ protected void doTestManyTimesAndAssertNoMemoryLeak(String testName, Runnable it long now = timer.elapsed(TimeUnit.MILLISECONDS); System.gc(); System.gc(); String msg = testName+" iteration " + i + " at " + Time.makeTimeStringRounded(now) + " (delta "+Time.makeTimeStringRounded(now-last)+"), using "+ - ((AbstractManagementContext)managementContext).getGarbageCollector().getUsageString(); + ((AbstractManagementContext)managementContext).getGarbageCollector().getUsageString()+ + "; weak-refs app="+Iterables.size(weakApps.keySet())+" and locs="+Iterables.size(weakLocs.keySet()); LOG.info(msg); if (i>=100 && memUsedNearStart<0) { // set this the first time we've run 100 times (let that create a baseline with classes loaded etc) @@ -112,20 +120,6 @@ protected void doTestManyTimesAndAssertNoMemoryLeak(String testName, Runnable it BrooklynStorage storage = ((ManagementContextInternal)managementContext).getStorage(); Assert.assertTrue(storage.isMostlyEmpty(), "Not empty storage: "+storage); - DataGrid dg = ((BrooklynStorageImpl)storage).getDataGrid(); - Set keys = dg.getKeys(); - for (String key: keys) { - ConcurrentMap v = dg.getMap(key); - if (v.isEmpty()) continue; - // TODO currently we remember ApplicationUsage - if (key.contains("usage-application")) { - Assert.assertTrue(v.size() <= iterations, "Too many usage-application entries: "+v.size()); - continue; - } - - Assert.fail("Non-empty key in datagrid: "+key+" ("+v+")"); - } - ConcurrentMap schedulers = ((BasicExecutionManager)managementContext.getExecutionManager()).getSchedulerByTag(); // TODO would like to assert this // Assert.assertTrue( schedulers.isEmpty(), "Not empty schedulers: "+schedulers); @@ -134,14 +128,21 @@ protected void doTestManyTimesAndAssertNoMemoryLeak(String testName, Runnable it // memory leak detection only applies to subclasses who run lots of iterations if (checkMemoryLeaks()) - assertNoMemoryLeak(memUsedNearStart); + assertNoMemoryLeak(memUsedNearStart, iterations); } - protected void assertNoMemoryLeak(long memUsedPreviously) { + protected void assertNoMemoryLeak(long memUsedPreviously, int iterations) { System.gc(); System.gc(); long memUsedAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long memChange = memUsedAfter - memUsedPreviously; Assert.assertTrue(memChange < numIterations()*ACCEPTABLE_LEAK_PER_ITERATION + MEMORY_MARGIN_OF_ERROR, "Leaked too much memory: "+Strings.makeJavaSizeString(memChange)); + + // TODO Want a stronger assertion than this - it just says we don't have more apps than we created! + int numApps = Iterables.size(weakApps.keySet()); + assertTrue(numApps <= iterations, "numApps="+numApps+"; iterations="+iterations); + + int numLocs = Iterables.size(weakLocs.keySet()); + assertTrue(numLocs <= iterations, "numLocs="+numLocs+"; iterations="+iterations); } protected void doTestStartAppThenThrowAway(String testName, final boolean stop) { @@ -164,6 +165,7 @@ public void run() { protected TestApplication newApp() { final TestApplication result = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext); + weakApps.put(app, null); TestEntity entity = result.createAndManageChild(EntitySpec.create(TestEntity.class)); result.subscriptions().subscribe(entity, TestEntity.NAME, new SensorEventListener() { @Override public void onEvent(SensorEvent event) { @@ -172,4 +174,10 @@ protected TestApplication newApp() { entity.sensors().set(TestEntity.NAME, "myname"); return result; } + + protected SimulatedLocation newLoc() { + SimulatedLocation result = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class)); + weakLocs.put(result, null); + return result; + } }