diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/management/internal/MonitoringManager.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/management/internal/MonitoringManager.java
index bfaf2a4..2b00dd3 100644
--- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/management/internal/MonitoringManager.java
+++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/management/internal/MonitoringManager.java
@@ -63,7 +63,10 @@ public class MonitoringManager {
}
/**
- * Invoke an operation over a managed type.
+ *
Invoke an operation over a managed type.
+ *
+ * This method is not thread-safe, it's the user's responsibility to
+ * make the operations of the managed type synchronized if necessary.
*
* @param managedType
* A type annotated with {@link Managed}. This method will create
@@ -81,7 +84,7 @@ public class MonitoringManager {
* In case the operation doesn't exist or have a different
* signature
*/
- public synchronized Object invoke(ManagedType managedType, String actionName,
+ public Object invoke(ManagedType managedType, String actionName,
Object[] params) {
if ( managedTypes.contains(managedType) ) {
activateContexts(managedType.getType());
@@ -112,14 +115,17 @@ public class MonitoringManager {
}
/**
- * Retrieve the current value of a property from a managed type. Properties
- * are attributes annotated with {@link Property}.
+ * Retrieve the current value of a property from a managed type. Properties
+ * are attributes annotated with {@link Property}.
+ *
+ * This method is not thread-safe, it's the user's responsibility to
+ * create the property's access methods from the managed type synchronized if necessary.
*
* @param managedType The type that has the property the client wants to know the value of.
* @param propertyName The name of the property
* @return The current value of the property
*/
- public synchronized Object getProperty(ManagedType managedType, String propertyName) {
+ public Object getProperty(ManagedType managedType, String propertyName) {
if ( managedTypes.contains(managedType) ) {
Method getterMethod = managedType.getFields().get(propertyName).getGetterMethod();
@@ -153,14 +159,17 @@ public class MonitoringManager {
}
/**
- * Sets a new value for a property contained inside a managed type. A property
- * is an attribute annotated with {@link Property}.
+ * Sets a new value for a property contained inside a managed type. A property
+ * is an attribute annotated with {@link Property}.
+ *
+ * This method is not thread-safe, it's the user's responsibility to
+ * create the property's access methods from the managed type synchronized if necessary.
*
* @param managedType The type that has access to the property
* @param propertyName The name of the property
* @param newValue The new value of the property
*/
- public synchronized void setProperty(ManagedType managedType, String propertyName,
+ public void setProperty(ManagedType managedType, String propertyName,
Object newValue) {
if ( managedTypes.contains(managedType) ) {
diff --git a/impl/core/src/test/java/management/ManagedClassStore.java b/impl/core/src/test/java/management/ManagedClassStore.java
deleted file mode 100644
index 5645590..0000000
--- a/impl/core/src/test/java/management/ManagedClassStore.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package management;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.enterprise.context.ApplicationScoped;
-
-import br.gov.frameworkdemoiselle.management.internal.ManagedType;
-
-@ApplicationScoped
-public class ManagedClassStore {
-
- private List managedTypes = new ArrayList();
-
-
- public List getManagedTypes() {
- return managedTypes;
- }
-
- public void addManagedTypes(Collection managedTypes){
- this.managedTypes.addAll(managedTypes);
- }
-
-}
diff --git a/impl/core/src/test/java/management/ManagementBootstrapTestCase.java b/impl/core/src/test/java/management/ManagementBootstrapTestCase.java
index 50d30be..73c93f8 100644
--- a/impl/core/src/test/java/management/ManagementBootstrapTestCase.java
+++ b/impl/core/src/test/java/management/ManagementBootstrapTestCase.java
@@ -6,6 +6,7 @@ import java.util.List;
import management.testclasses.DummyManagedClass;
import management.testclasses.DummyManagedClassPropertyError;
import management.testclasses.DummyManagementExtension;
+import management.testclasses.ManagedClassStore;
import org.jboss.arquillian.container.test.api.Deployer;
import org.jboss.arquillian.container.test.api.Deployment;
@@ -44,7 +45,7 @@ public class ManagementBootstrapTestCase {
new File("src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension"),
"services/javax.enterprise.inject.spi.Extension")
.addPackages(false, ManagementBootstrapTestCase.class.getPackage())
- .addClasses(DummyManagementExtension.class,DummyManagedClass.class);
+ .addClasses(DummyManagementExtension.class,DummyManagedClass.class,ManagedClassStore.class);
}
/**
@@ -63,7 +64,7 @@ public class ManagementBootstrapTestCase {
new File("src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension"),
"services/javax.enterprise.inject.spi.Extension")
.addPackages(false, ManagementBootstrapTestCase.class.getPackage())
- .addClasses(DummyManagementExtension.class,DummyManagedClassPropertyError.class);
+ .addClasses(DummyManagementExtension.class,DummyManagedClassPropertyError.class,ManagedClassStore.class);
}
/**
diff --git a/impl/core/src/test/java/management/ManagementTestCase.java b/impl/core/src/test/java/management/ManagementTestCase.java
new file mode 100644
index 0000000..4df0bff
--- /dev/null
+++ b/impl/core/src/test/java/management/ManagementTestCase.java
@@ -0,0 +1,128 @@
+package management;
+
+import java.io.File;
+
+import junit.framework.Assert;
+import management.testclasses.DummyManagedClass;
+import management.testclasses.DummyManagementExtension;
+import management.testclasses.ManagedClassStore;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.FileAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import test.LocaleProducer;
+import br.gov.frameworkdemoiselle.DemoiselleException;
+import br.gov.frameworkdemoiselle.util.Beans;
+
+/**
+ * Test case that simulates a management extension and tests if properties and operations on a managed class can be
+ * easily accessed and invoked.
+ *
+ * @author serpro
+ */
+@RunWith(Arquillian.class)
+public class ManagementTestCase {
+
+ @Deployment
+ public static JavaArchive createMultithreadedDeployment() {
+ return ShrinkWrap
+ .create(JavaArchive.class)
+ .addClass(LocaleProducer.class)
+ .addPackages(true, "br")
+ .addAsResource(new FileAsset(new File("src/test/resources/test/beans.xml")), "beans.xml")
+ .addAsManifestResource(
+ new File("src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension"),
+ "services/javax.enterprise.inject.spi.Extension")
+ .addPackages(false, ManagementTestCase.class.getPackage())
+ .addClasses(DummyManagementExtension.class, DummyManagedClass.class, ManagedClassStore.class);
+ }
+
+ @Test
+ public void testReadProperty() {
+ DummyManagedClass managedClass = Beans.getReference(DummyManagedClass.class);
+ managedClass.setName("Test Name");
+
+ // store é nossa extensão de gerenciamento falsa, então estamos testando um "cliente" acessando
+ // nosso tipo gerenciado DummyManagedClass remotamente.
+ ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
+ Object name = store.getProperty(DummyManagedClass.class, "name");
+ Assert.assertEquals("Test Name", name);
+ }
+
+ @Test
+ public void testWriteProperty() {
+ // store é nossa extensão de gerenciamento falsa, então estamos testando um "cliente" definindo
+ // um novo valor em uma propriedade de nosso tipo gerenciado DummyManagedClass remotamente.
+ ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
+ store.setProperty(DummyManagedClass.class, "name", "Test Name");
+
+ DummyManagedClass managedClass = Beans.getReference(DummyManagedClass.class);
+ Assert.assertEquals("Test Name", managedClass.getName());
+ }
+
+ @Test
+ public void testReadAWriteOnly() {
+
+ ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
+
+ try {
+ store.getProperty(DummyManagedClass.class, "writeOnlyProperty");
+ Assert.fail();
+ } catch (DemoiselleException de) {
+ // SUCCESS
+ }
+
+ }
+
+ @Test
+ public void testWriteAReadOnly() {
+
+ ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
+
+ try {
+ store.setProperty(DummyManagedClass.class, "readOnlyProperty", "New Value");
+ Assert.fail();
+ } catch (DemoiselleException de) {
+ // SUCCESS
+ }
+
+ }
+
+ @Test
+ public void testInvokeOperation() {
+
+ ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
+
+ try {
+ store.setProperty(DummyManagedClass.class, "firstFactor", new Integer(10));
+ store.setProperty(DummyManagedClass.class, "secondFactor", new Integer(15));
+ Integer response = (Integer) store.invoke(DummyManagedClass.class, "sumFactors");
+ Assert.assertEquals(new Integer(25), response);
+ } catch (DemoiselleException de) {
+ Assert.fail(de.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testInvokeNonAnnotatedOperation() {
+
+ ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
+
+ try {
+ // O método "nonOperationAnnotatedMethod" existe na classe DummyManagedClass, mas não está anotado como
+ // "@Operation", então
+ // ela não pode ser exposta para extensões.
+ store.invoke(DummyManagedClass.class, "nonOperationAnnotatedMethod");
+ Assert.fail();
+ } catch (DemoiselleException de) {
+ // SUCCESS
+ }
+
+ }
+}
diff --git a/impl/core/src/test/java/management/NotificationTestCase.java b/impl/core/src/test/java/management/NotificationTestCase.java
index 0165f5e..b37a000 100644
--- a/impl/core/src/test/java/management/NotificationTestCase.java
+++ b/impl/core/src/test/java/management/NotificationTestCase.java
@@ -53,7 +53,7 @@ public class NotificationTestCase {
.addAsManifestResource(
new File("src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension"),
"services/javax.enterprise.inject.spi.Extension")
- .addPackages(false, ManagementBootstrapTestCase.class.getPackage())
+ .addPackages(false, NotificationTestCase.class.getPackage())
.addClasses(DummyNotificationListener.class,DummyManagedClass.class);
}
diff --git a/impl/core/src/test/java/management/testclasses/DummyManagedClass.java b/impl/core/src/test/java/management/testclasses/DummyManagedClass.java
index 5d0b9b0..a041d14 100644
--- a/impl/core/src/test/java/management/testclasses/DummyManagedClass.java
+++ b/impl/core/src/test/java/management/testclasses/DummyManagedClass.java
@@ -12,15 +12,24 @@ import br.gov.frameworkdemoiselle.management.annotation.validation.AllowedValues
public class DummyManagedClass {
@Property
+ private String name;
+
+ @Property
@AllowedValues(allows={"f","m","F","M"},valueType=ValueType.INTEGER)
private Integer id;
@Property
+ private Integer firstFactor , secondFactor;
+
+ @Property
private String uuid;
@Property
private String writeOnlyProperty;
+ @Property
+ private String readOnlyProperty = "Default Value";
+
/**
* Propriedade para testar detecção de métodos GET e SET quando propriedade tem apenas uma letra.
*/
@@ -71,4 +80,87 @@ public class DummyManagedClass {
this.uuid = UUID.randomUUID().toString();
return this.uuid;
}
+
+
+ public String getName() {
+ return name;
+ }
+
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ public String getReadOnlyProperty() {
+ return readOnlyProperty;
+ }
+
+
+ public Integer getFirstFactor() {
+ return firstFactor;
+ }
+
+
+ public void setFirstFactor(Integer firstFactor) {
+ this.firstFactor = firstFactor;
+ }
+
+
+ public Integer getSecondFactor() {
+ return secondFactor;
+ }
+
+
+ public void setSecondFactor(Integer secondFactor) {
+ this.secondFactor = secondFactor;
+ }
+
+ @Operation
+ public Integer calculateFactorsNonSynchronized(Integer firstFactor , Integer secondFactor){
+ setFirstFactor(firstFactor);
+ setSecondFactor(secondFactor);
+
+ try {
+ int temp = firstFactor + secondFactor;
+ Thread.sleep( (long)(Math.random() * 100));
+
+ temp = temp + firstFactor;
+ Thread.sleep( (long)(Math.random() * 100));
+
+ temp = temp + secondFactor;
+ Thread.sleep( (long)(Math.random() * 100));
+
+ return temp;
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Operation
+ public synchronized Integer calculateFactorsSynchronized(Integer firstFactor , Integer secondFactor){
+ setFirstFactor(firstFactor);
+ setSecondFactor(secondFactor);
+
+ try {
+ int temp = firstFactor + secondFactor;
+ Thread.sleep( (long)(Math.random() * 100));
+
+ temp = temp + firstFactor;
+ Thread.sleep( (long)(Math.random() * 100));
+
+ temp = temp + secondFactor;
+ Thread.sleep( (long)(Math.random() * 100));
+
+ return temp;
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void nonOperationAnnotatedMethod(){
+ System.out.println("Test");
+ }
+
+
}
diff --git a/impl/core/src/test/java/management/testclasses/DummyManagementExtension.java b/impl/core/src/test/java/management/testclasses/DummyManagementExtension.java
index a1e0c3b..8ce01af 100644
--- a/impl/core/src/test/java/management/testclasses/DummyManagementExtension.java
+++ b/impl/core/src/test/java/management/testclasses/DummyManagementExtension.java
@@ -4,7 +4,6 @@ import java.util.List;
import javax.inject.Inject;
-import management.ManagedClassStore;
import br.gov.frameworkdemoiselle.management.extension.ManagementExtension;
import br.gov.frameworkdemoiselle.management.internal.ManagedType;
diff --git a/impl/core/src/test/java/management/testclasses/ManagedClassStore.java b/impl/core/src/test/java/management/testclasses/ManagedClassStore.java
new file mode 100644
index 0000000..94a907d
--- /dev/null
+++ b/impl/core/src/test/java/management/testclasses/ManagedClassStore.java
@@ -0,0 +1,66 @@
+package management.testclasses;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import br.gov.frameworkdemoiselle.management.internal.ManagedType;
+import br.gov.frameworkdemoiselle.management.internal.MonitoringManager;
+import br.gov.frameworkdemoiselle.util.Beans;
+
+/**
+ * Dummy class that stores managed types detected by the management bootstrap
+ * and can read/write properties and invoke operations on them, simulating a management
+ * extension like JMX or SNMP.
+ *
+ * @author serpro
+ *
+ */
+@ApplicationScoped
+public class ManagedClassStore {
+
+ private List managedTypes = new ArrayList();
+
+
+ public List getManagedTypes() {
+ return managedTypes;
+ }
+
+ public void addManagedTypes(Collection managedTypes){
+ this.managedTypes.addAll(managedTypes);
+ }
+
+ public void setProperty(Class> managedClass , String attributeName , Object newValue){
+ MonitoringManager manager = Beans.getReference(MonitoringManager.class);
+ for (ManagedType type : manager.getManagedTypes()){
+ if (type.getType().equals(managedClass)){
+ manager.setProperty(type, attributeName, newValue);
+ break;
+ }
+ }
+ }
+
+ public Object getProperty(Class> managedClass , String attributeName ){
+ MonitoringManager manager = Beans.getReference(MonitoringManager.class);
+ for (ManagedType type : manager.getManagedTypes()){
+ if (type.getType().equals(managedClass)){
+ return manager.getProperty(type, attributeName);
+ }
+ }
+
+ return null;
+ }
+
+ public Object invoke(Class> managedClass , String operation , Object... params){
+ MonitoringManager manager = Beans.getReference(MonitoringManager.class);
+ for (ManagedType type : manager.getManagedTypes()){
+ if (type.getType().equals(managedClass)){
+ return manager.invoke(type, operation, params);
+ }
+ }
+
+ return null;
+ }
+}
--
libgit2 0.21.2