Abstract or annotated class instead interface as MXBean - java

Is there a way to use abstract or annotated class as MXBean descriptor? I have interface like:
#MXBean
public interface Peer {
public String getName();
}
and want that MXBean to be combined in class with more local-side-only methods like:
public class PeerCombinedMXBean {
// Expose this as MXBean attribute
public String getName() { ... }
// This method is local-instance-oriented
public boolean isValid() { ... }
}
I need model like above to avoid chain-in proxy object instead to use complex half-proxified instance like:
PeerCombinedMXBean peer = JMX.newMXBeanProxy(connection, name, PeerCombinedMXBean.class);
if (peer.isValid()) System.out.println(peer.getName());
Edit
This question is related to java.net article. What is they progress? Can I use MBeans with annotation safely now?

What I ended up doing for this was writing a custom annotation that you place on a method or property. Then, I implemented the DynamicMBean interface in such a way that it parsed out the annotations on the class in question and then registers them with the PlatformMBeanServer. As far as I know, there are no public implementations of this available, I also searched extensively about this topic before I just did it myself.
For example, here is the class that I wish to manage from JConsole:
public class Foo
{
// In JMX Console
#Managed
private boolean isBar;
// Not in JMX Console
private boolean isFoo;
// In JMX Console
#Managed
public String getClassName()
{
return Foo.class.getName();
}
}
Then, when my application starts up, I register an instance of this class using my implementation of DynamicMBean and parse out the annotations.

Related

Is it safe to use String as a return type of a bean in spring?

#Configuration
public class Product {
#Bean("xyz")
public String getMethod() {
return "abc";
}
}
#Component
public class Test {
String b;
Test(String xyz) {
this.b = xyz;
}
}
Is this any harm with this approach? I am trying to make change in the existing code where I am replacing the #Value with the getter as the method parameter. As I don't want to change the structure of the existing code I am trying to inject the method as bean as a replacement to #Value.
I suggest you to keep the #Value annotation instead of the whole #Bean configurations.
Why?
What if the getMethod()'s returned value needs to be changed very often? Everytime when you're changing something in the Product class, during build time it needs to be recompiled. What happens if the project is getting bigger and you're using this approach? It leads to longer build time and the more important thing is that this solution is not intuitive and it's hard to keep it clean. Don't think about complex solutions only to make the code look fancy. When you need to inject String values, the easiest approach is to create properties files (which won't get recompiled) and use the #Value annotation.
Now, if you want to add new methods without changing the structure of the existing code there are some patterns which you can apply like decorator pattern.
The main idea is simple: you're creating a decorator class which has an object of the type you need.
The easiest example (which you'll find everywhere on the internet) is the classic Shape example:
public interface Shape {
String someMethod();
}
#Component
public class CustomShape implements Shape { //implement the method here }
And here is the decorator:
public interface ShapeDecorator {
String someMethodExtended();
void someExtraMethod();
}
#Component
public class CustomShapeDecorator implements ShapeDecorator{
#Autowired
// #Qualifier - optional (only if you have more Shape implementations)
private Shape shape;
// now you can either:
// 1. provide new methods
#Override
public void someExtraMethod(){
System.out.println("Hello world!");
}
// 2. or you can EXTEND the Shape's "someMethod()" implementation
#Override
public String someMethodExtended(){
String oldString = this.shape.someMethod();
return oldString + " EXTENDED";
}
}

Guice inject based on annotation value

I would like to use goolge/guice inject a value based on a class i provide with the annotation.
AutoConfig annotation
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.PARAMETER, ElementType.FIELD })
public #interface AutoConfig {
// default null not possible
Class<? extends Provider<? extends ConfigLoader<?>>> provider() default XMLAutoConfigProvider.class;
}
This is my annotation which allows configuring the type of config, that should be used for the annotated fields.
Usecase:
#AutoConfig()
ConfigLoader<?> defaultConfig;
#AutoConfig(provider = JsonConfigProvider)
ConfigLoader<?> jsonConfig;
I want to have two configs, one default/xml one and a json one. They will probably never occur in the same class at the same time. But i don't know when the one or the other is used. I used the approach with a class because they are provided by some dependencies/libs and this annotation will be used for some (plugable) submodules.
MyGuiceModule
public class MyGuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(new TypeLiteral<ConfigLoader<?>>() {})
.annotatedWith(AutoConfig.class)
.toProvider(autoConfig.provider());
}
}
This the critical part, i just cannot imagine how to implement it.
So basically i just want to use the provider class specified in the annotation.
Its not necessary to use the provider class here too. Because autoConfig.provider().newInstance() is basically all i need. (I need to use a setter on the new instance but thats all i want to do at this place)
To sum it up all i really want to do is push the annotation (or its values to the provider) either using the get(AutoConfig autoConfig) or in the constructor.
Currently i only use the constructor to inject the configFile value i want to set on the newly generated config instance.
If you know that #AutoConfig(provider = JsonConfigProvider) ConfigLoader<?> jsonConfig is going to return you exactly the results of jsonConfigProvider.get(), and JsonConfigProvider obviously has a public parameterless constructor for newInstance to work, why wouldn't you just ask for a JsonConfigProvider in the first place?
Fundamentally Guice is just a Map<Key, Provider> with fancy wrapping. The bad news is that this makes variable bindings like "bind Foo<T> for all T" impossible to express concisely, and that includes your "bind #Annotation(T) Foo for all T". The good news is that you still have two options.
Bind each provider separately
Though you can't inspect annotations during provision (or tell Guice to do so for you), Guice will compare annotations using their equals methods if you bind an annotation instance rather than an annotation class (the way you would with Names.named("some-name")). This means that you can bind a ConfigLoader<?> with each expected annotation in a Module. Of course, this also means you'll have to have a list of possible ConfigLoader Providers available at configuration time, but they have to be compile-time constants anyway if you're using them as annotation parameters.
This solution works with constructor injection as well, but for fields you'll need both #Inject and #AutoConfig(...), and AutoConfig will need to keep its #BindingAnnotation meta-annotation.
To do this, you're going to have to write an implementation of your annotation, the way Guice does with NamedImpl. Note that the implementations of equals and hashCode must match the ones Java provides in java.lang.Annotation. Then it's just a matter of (redundantly) binding like this:
for(Class<ConfigLoader<?>> clazz : loaders) {
bind(ConfigLoader.class).annotatedWith(new AutoConfigImpl(clazz))
.toProvider(clazz);
}
The definition of equals is up to you, which means you can (and should) bind #AutoConfig(ConfigEnum.JSON) and keep the Guice bindings in your modules rather than specifying your requested implementation all over your codebase.
Use custom injections
You can also use custom injections to search your injected types for custom annotations like #AutoConfig. At this point, you'd be using Guice as a platform to interpret #AutoConfig instead of #Inject, which means that constructor injection won't work but that you can control your injection based on the injected instance, field name, field annotation, annotation parameters, or any combination thereof. If you choose this style, you can drop #BindingAnnotation from AutoConfig.
Use the example in the wiki article linked above as your template, but at minimum you'll need to:
Use bindListener on Binder or AbstractModule to match types that need this custom injection.
In the TypeListener you bind, search injected types for #AutoConfig-annotated fields, and if they have any matching methods then bind those matching methods to a MembersInjector or InjectionListener. You'll probably want to tease the class literal out of the annotation instance here, and pass in the Field and Class as constructor arguments to the MembersInjector/InjectionListener.
In the MembersInjector or InjectionListener you write, instantiate the provider and set the field to the instance the provider provides.
This is a very powerful feature, which would futher allow you to--for instance--automatically provide the configuration based on which instance you're injecting into or based on the name of the field. However, use it carefully and document it heavily, because it may be counter-intuitive to your coworkers that Guice is providing for an annotation other than #Inject. Also bear in mind that this won't work for constructor injection, so refactoring from field injection to constructor injection will cause Guice to complain that it's missing a required binding to instantiate the class.
I had a similar problem. I wanted to use a custom annotation that receives a enum param to choose the implementation. After a lot of research, debug and testing, I came to the following solution:
//enum to define authentication types
public enum AuthType {
Ldap, Saml
}
//custom annotation to be used in injection
#Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
#BindingAnnotation
public #interface Auth {
AuthType value();
}
//defintion of authenticator
public interface Authenticator {
public void doSomehting();
}
//Authenticator implementations
public class LdapAuthenticator implements Authenticator {
#Override
public void doSomehting() {
// doing ldap stuff
}
}
public class SamlAuthenticator implements Authenticator {
#Override
public void doSomehting() {
// doing saml stuff
}
}
public class MyModule extends AbstractModule {
// annotate fields to bind to implementations
private #Auth(AuthType.Ldap) Authenticator ldap;
private #Auth(AuthType.Saml) Authenticator saml;
#Override
protected void configure() {
//bind the implementation to the annotation from field
bindAnnotated("ldap", LdapAuthenticator.class);
bindAnnotated("saml", SamlAuthenticator.class);
}
private void bindAnnotated(String fieldName, Class<? extends Authenticator> implementation) {
try {
//get the annotation from fields, then bind it to implementation
Annotation ann = MyModule.class.getDeclaredField(fieldName).getAnnotation(Auth.class);
bind(Authenticator.class).annotatedWith(ann).to(implementation);
} catch (NoSuchFieldException | SecurityException e) {
throw new RuntimeException(e);
}
}
}
//usage: add #Auth(<AuthType>) to the dependency
public class ClientClass {
private Authenticator authenticator;
#Inject
public ClientClass(#Auth(AuthType.Ldap) Authenticator authenticator) {
this.authenticator = authenticator;
}
}
Check the documentation of Binder
I tested the Jeff Bowman solution, but it apparently works only binding to providers
As a BindingAnnotations#binding-annotations-with-attributes states equals() and hashCode() should be properly implemented. So given that there is MyAnnotation
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER})
public #interface MyAnnotation {
SomeEnum value() default SomeEnum.A;
}
which is used to specify SomeInterface implementation(SomeDefault and SomeOther), SomeModule class could look like
public class SomeModule extends AbstractModule {
#Override
protected void configure() {
bind(Key.get(SomeInterface.class, createAnnotationClass(A))).to(SomeDefault.class);
// more common binding expresion
bind(SomeInterface.class).annotatedWith(createAnnotationClass(B)).to(SomeDefault.class);
}
private Annotation createAnnotationClass(SomeEnum someEnum) {
return new MyAnnotation() {
#Override
public SomeEnum value() {
return someEnum;
}
#Override
public Class<? extends Annotation> annotationType() {
return MyAnnotation.class;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyAnnotationCl myAnnoCl = (MyAnnotationCl) o;
return A == myAnnoCl.getValue();
}
#Override
public int hashCode() {
// from java annotation documentation
return (127 * "value".hashCode()) ^ value().hashCode();
}
};
}
}
Then annotation could be used as follows:
public class DoSomethingWithSomething {
private final SomeInterface someImplementation;
#Inject
public DoSomethingWithSomething(
#MyAnnotation SomeInterface someDefault
// #MyAnnotation(A) SomeInterface someDefault
// #MyAnnotation(B) SomeInterface someOther
) {
this.someImplementation = someDefault;
}
}

giving access to only few properties of a class?

I have below the class.
SomeClass.java
public class SomeClass {
private String name;
private String id;
private String access;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAccess() {
return access;
}
public void setAccess(String access) {
this.access = access;
}
public void doSomeFunctionality(){
//does some logic using name and id
}
}
Now I have to expose only few methods of above class to clients. I can do as below.
SomeOtherClass.java
public class SomeOtherClass {
private SomeClass someClass = new SomeClass();
public void setName(String name) {
someClass.setName(name);
}
public void setId(String id) {
this.setId(id);
}
}
By doing like above i can restrict one method not accessible to clients and am exposing only required methods. Now client instantiates SomeClass and populates the data into someClass property of SomeOtherClass.java.
But now how can i get the populated data from SomeOtherClass.java?
public SomeClass getSomeClass() {
return someClass;
}
If i provide getter method to get SomeClass in SomeOtherClass.java like above then even clients can also access it which i dont want to do.
But if i can get populated someClass instance directly then i can simply call doSomeFunctionality() on the same instance. like getSomeClass().doSomeFunctionality();
How can i overcome above scenario?
Thanks!
Your question seems confused, but I think this is the answer you are looking for,
Your approach to letting the client get the information should be exactly the same as letting them set it. You should not provide access to the inner SomeClass - that defeats the whole point. So if you want to provide both read and write access to only the name property, your outer class should look like:
public class SomeOtherClass {
private SomeClass someClass = new SomeClass();
public void setName(String name) {
someClass.setName(name);
}
public String getName() {
return someClass.getName();
}
}
You don't have to make the properties they can get the same as the properties they can set. You could also allow them to 'get' the ID, for example, but not set it. If you want them to have access to all the properties, provide getters for all properties in SomeOtherClass. If that is the case you might want to consider creating an interface which specifies all the getter methods and is implemented by both SomeClass and SomeOtherClass, with both classes also implementing the setter methods they require.
There are other architectural approaches if you always want to provide full 'read' access but restricted 'write' access, which we can go into if you ask.
If you create an interface that is implemented by the class that will be used by the client, but then the client obtains its reference to the instantiation of the class using the interface, even if you have public properties, members, ...etc., the client will only see those provided/defined by the interface.
Don't return the SomeClass object in a getter, just create a getter for the field(s) you want to make available:
public String getName() {
return someClass.getName();
}
I would suggest thinking about how you would separately test the pieces involved here. If we look at SomeOtherClass, right away we notice that it has a dependency on SomeClass--this is fine. Unfortunately, you hardwire the dependency to SomeClass by using the new operator. If you used a dependency injection framework (e.g., Spring or Guice) you could simply have the framework provide a fully configured instance of SomeClass to SomeOtherClass so that the instance could be used directly and SomeClass is no longer in the business of creating its own dependencies, but rather it goes about doing its useful work. Calling new on SomeClass in SomeOtherClass impedes your ability to test SomeOtherClass independently of SomeClass--you'll be integration testing unless you employ something like PowerMock, which really is better used in emergency situations like when you can't control third-party code. Hope it helps! P.S. all those setters and none for your dependency on SomeClass!

Can I have Spring's #Component on enum?

I'm using Spring 3.0.x and following the enum singleton pattern for one of my implementatons.
public enum Person implements Nameable {
INSTANCE;
public String getName(){
// return name somehow (Having a variable but omitted for brevity)
}
}
Recently we started to collecting those types via Spring so I need to add #Component to my class.
#Component
public enum Person implements Nameable {
INSTANCE;
public String getName(){
// return name somehow (Having a variable but omitted for brevity)
}
}
and collecting method is
#Autowired
public void collectNameables(List<Nameable> all){
// do something
}
After doing this I observed failures and cause was Spring cannot intialize enum classes (which is understandable).
My question is -
Is there any other way usign which I can mark my enum classes as a bean ?
Or i need to change my implementation?
If you really need to use enum-based singleton (despite the fact that Spring beans are singletons by default), you need to use some other way to register that bean in the Spring context. For example, you can use XML configuration:
<util:constant static-field="...Person.INSTANCE"/>
or implement a FactoryBean:
#Component
public class PersonFactory implements FactoryBean<Person> {
public Person getObject() throws Exception {
return Person.INSTANCE;
}
public Class<?> getObjectType() {
return Person.class;
}
public boolean isSingleton() {
return true;
}
}
You won't need to use the enum singleton pattern if you're using Spring to manage dependency injection. You can change your Person to a normal class. Spring will use the default scope of singleton, so all Spring-injected objects will get the same instance.

Description for Standard MBean

I want to make my Standard MBean verbose in JBoss jmx-console. DynamicMBean has getMBeanInfo() to do it. Method return MBeanInfo with description of MBean. But how I can to do the same thing for Standard MBean? E.g. I have following MBean interface:
public interface MyMBean {
String f();
}
... with following implementation:
public class My implements MyMBean {
public String f() {
return "test";
}
}
What should be done to add description in such example?
Thanks
For StandardMBeans there is no way for adding description or other meta information.
From the JavaDoc of MBeanInfo:
The remaining details of the MBeanInfo for a Standard MBean are not specified. This includes the description of the MBeanInfo and of any contained constructors, attributes, operations, and notifications; and the names and descriptions of parameters to constructors and operations.
So you need to use at least DynamicMBeans (or a ModelMBean or OpenMBean) for specifying this information. Spring can help you insofar as it allows the creation of DynamicMBeans via annotations, which at the end is even simpler to use than to write own StandardMBeans. Example (from the spring documentation) :
#ManagedResource(objectName="bean:name=testBean4",
description="My Managed Bean")
public class AnnotationTestBean {
private int age;
#ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15)
public int getAge() {
return age;
}
}
See this article for details.
You can do this via an xmbean-descriptor without the need to modify the existing mbean source code.
See How to add description for MBean method to see it in jmx-console of JBOSS for an answer to this.
The way to get the description information from Spring annotations #Managed* is just to declare a standard Spring "managed bean", and not an MBean or MXBean.
To do this, in your example, you must not implements the interface with "MBean" suffix.
Then, the bean will be detected as a standard "managed bean" when MBeanExporter will registerBeanInstance(..), and will be converted to a ModelMBean using all spring annotations, including descriptions of attributes, operations, parameters, etc..
As a requirement, you should declare in your spring context the MBeanExporter with AnnotationJmxAttributeSource, MetadataNamingStrategy, and MetadataMBeanInfoAssembler attributes, which can be simplified like this :
<bean id="mbeanExporter"
class="org.springframework.jmx.export.annotation.AnnotationMBeanExporter" />
or
<context:mbean-export />
And your managed bean should look like this (as explained by Roland) :
#Component("myManagedBean")
#ManagedResource(objectName="your.domain.jmx:name=MyMBean",
description="My MBean goal")
public class AnnotationTestBean {
private int age;
#ManagedAttribute(description="The age attribute", currencyTimeLimit=15)
public int getAge() {
return age;
}
#ManagedOperation(description = "Check permissions for the given activity")
#ManagedOperationParameters( {
#ManagedOperationParameter(name = "activity",
description = "The activity to check")
})
public boolean isAllowedTo(final String activity) {
// impl
}
}
Remember to not implements an MBean interface, which would be a StandardMBean !!

Categories

Resources