Is this class not a Java Bean? - java

I am trying to use existing Java classes to create a web service using Axis2.
When I send a request to the web service, Axis2 displays the following message:
[01 Nov 2012 16:37:05:244] classloader.BeanInfoCache: Unable to locate a BeanInfo cache for class ems.shared.Fti (stopClass=class java.lang.Object). This will negatively affect performance!
I'm not sure what that error means, but it makes me wonder if the ems.shared.Fti class doesn't satisfy all the requirements to being a Java Bean. Can you see anything wrong with this class?
package ems.shared;
import java.io.Serializable;
public class Fti implements Serializable
{
private static final long serialVersionUID = 7476379431395094501L;
public static final Fti UNDEFINED = new Fti(-1);
public static final Fti BROADCAST = new Fti((int) (Math.pow(2, 20) - 2));
private int fti;
public Fti() {
}
public Fti(int fti)
{
this.fti = fti;
}
public Fti(String fti)
{
try
{
this.fti = Integer.parseInt(fti);
}
catch (NumberFormatException e)
{
throw new IllegalArgumentException(fti + " is not a valid FTI");
}
}
public void setFti(int fti) {
this.fti = fti;
}
public int getFti() {
return fti;
}
public int asInt()
{
return this.fti;
}
#Override
public String toString()
{
return String.valueOf(fti);
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + fti;
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Fti other = (Fti) obj;
if (fti != other.fti)
return false;
return true;
}
}

BeanInfo is something separate. It was originally the mechanism by which a JavaBean would tell a Bean shell about itself, a la Visual Basic:
http://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s0503beaninfoexample01.html

BeanInfo instances are created by the JavaBean introspector (see the JRE Javadoc). As pointed out by duffymo, it is possible to provide the BeanInfo explicitly together with the JavaBean, in which case the introspector simply loads that BeanInfo. This is primarily used for UI components and is not mandatory. For a JavaBean that has no explicit BeanInfo, the introspector simply constructs the BeanInfo instance using reflection. This is what happens in your case.
The point is that the JRE doesn't cache BeanInfo objects. The reason is that it cannot do that without the risk of causing class loader leaks (see IZ67457 for an example of a bug caused by an attempt to cache these objects in certain versions of the IBM JRE). However, constructing a BeanInfo object using reflection is a costly operation. Therefore Axis2 has its own BeanInfo cache. That cache is carefully designed to avoid class loader leaks.
The message that you get (which BTW is a warning, not an error) simply says that in your case Axis2 is not able to use a cached BeanInfo object. There are two possible reasons for that: either you are in a scenario where it is impossible to cache the BeanInfo object without potentially causing a class loader leak, or you are in a scenario where the BeanInfo object could be cached without causing a class loader leak but that is not supported by the BeanInfo cache (i.e. you are encountering a limitation in the cache implementation).
To analyze this further, you need to determine which class loader loads the Fti class, which class loader loads the BeanInfoCache class (i.e. the axis2-kernel JAR) and how these class loaders are related to each other (e.g. are they related by a parent-child relationship).

Related

Resolving Dependencies in JNI DefineClass

I am writing an application using the JVMTI. I am trying to instrument the bytecode: by injecting method calls on every method entry.
I know how to do that, but the problem is in the instrument class, say it's called Proxy, which I load using the JNI function DefineClass. My Proxy has a few dependencies in Java Class Library, currently just java.lang.ThreadLocal<Boolean>.
Now, say I have this, where inInstrumentMethod is a plain boolean:
public static void onEntry(int methodID)
{
if (inInstrumentMethod) {
return;
} else {
inInstrumentMethod = true;
}
System.out.println("Method ID: " + methodID);
inInstrumentMethod = false;
}
The code compiles and works. However, if I make inInstrumentMethod a java.lang.ThreadLocal<Boolean>, I get a NoClassDefFoundError. The code:
private static ThreadLocal<Boolean> inInstrumentMethod = new ThreadLocal<Boolean>() {
#Override protected Boolean initialValue() {
return Boolean.FALSE;
}
};
public static void onEntry(int methodID)
{
if (inInstrumentMethod.get()) {
return;
} else {
inInstrumentMethod.set(true);
}
System.out.println("Method ID: " + methodID);
inInstrumentMethod.set(false);
}
My guess is that the dependencies have not been resolved correctly, and java.lang.ThreadLocal was not loaded (and thus could not be found). The question is, then, how do I force Java to load java.lang.ThreadLocal? I don't think I could use DefineClass in this case; is there an alternative?
I don’t think that there is a problem resolving the standard class java.lang.ThreadLocal, but rather with the inner class extending it, generated by
new ThreadLocal<Boolean>() {
#Override protected Boolean initialValue() {
return Boolean.FALSE;
}
};
Solving this via DefineClass might indeed be impossible due to the circular dependency between the inner and outer class, so there’s no order which allows to define them, unless you have a full-fledged ClassLoader that returns the classes on demand.
The simplest solution is to avoid the generation of an inner class at all, which is possible with Java 8:
private static ThreadLocal<Boolean> inInstrumentMethod
= ThreadLocal.withInitial(() -> Boolean.FALSE);
If you use a version prior to Java 8, you can’t use it that way, so the best solution in that case, is to rewrite the code to accept the default value of null as initial value, eliminating the need to specify a different initial value:
private static ThreadLocal<Boolean> inInstrumentMethod = new ThreadLocal<>();
public static void onEntry(int methodID)
{
if (inInstrumentMethod.get()!=null) {
return;
} else {
inInstrumentMethod.set(true);
}
System.out.println("Method ID: " + methodID);
inInstrumentMethod.set(null);
}
You could also convert that anonymous inner class to a top level class. Since then, that class has no dependency to what was formerly its outer class, defining that subtype of ThreadLocal first, before defining the class using it, should solve the issue.

Hadoop singleton pattern uasge

I'm trying to implement singleton which is going to cache and validate configuration of map reduce jobs in hadoop. Let's name it ConfigurationManager.
Here is what I have for now:
public class ConfigurationManager {
private static volatile ConfigurationManager instance;
private static final String CONF_NAME = "isSomethingEnabled";
private boolean isSomethingEnabled;
private ConfigurationManager(Configuration configuration) {
this.isSomethingEnabled= configuration.getBoolean(CONF_NAME, false);
}
public static void init(Configuration configuration) {
if (instance == null) {
synchronized (ConfigurationManager.class) {
if (instance == null) {
this.instance = new ConfigurationManager(configuration);
}
}
}
}
public static ConfigurationManager get() {
return instance;
}
public boolean isSomethingEnabled() {
return isSomethingEnabled;
}
}
As you can see it is designed to be thread-safe. Moreover it is not standard singleton: I separated initialization and accessor methods not to enforce presence of hadoop's Configuration instance on get call. So to use it I prematurely call init in the ancestor of Tool and then trying to access my singleton using get in reducers (like this ConfigurationManager.get().isSomethingEnabled()), but for some reasons get returns null. Could somebody, please, explain such a behaviour? Maybe maps/reducers are initiated as separate processes?
Each reduce task runs on a different jvm. Which would explain the null.
You can do it per reduce task in : Reducer - configure

Alternate method of BeanInfo creation?

I recently moved my spring application from java 1.6 to java 1.8. This has caused the spring bootstrapping to take an order of magnitude longer (20s before, 4mins now). Tracing the cause has led me to the CachedIntrospectionResults class, which is created for every bean. When created it calls,
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
Introspector then creates the bean info, in java 1.6, it calls
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass);
}
However in java 1.8 it now calls,
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass, findCustomizerClass(this.beanClass));
}
private static Class<?> findCustomizerClass(Class<?> type) {
String name = type.getName() + "Customizer";
try {
type = ClassFinder.findClass(name, type.getClassLoader());
// Each customizer should inherit java.awt.Component and implement java.beans.Customizer
// according to the section 9.3 of JavaBeans™ specification
if (Component.class.isAssignableFrom(type) && Customizer.class.isAssignableFrom(type)) {
return type;
}
}
catch (Exception exception) {
// ignore any exceptions
}
return null;
}
This method as far as I can see was added with java 1.7, and since I don't define any customizer classes, it searches my full classpath then throws an exception which ends up taking a few hundred ms. The result being that each bean takes ~500ms to init. A huge hit to startup time.
I am now trying to find a way to work around this problem,
The spring documentation says to implement a BeanInfoFactory in order to customize the beanInfo creation. But I can't find anywhere that says how to actaually create BeanInfo for a provided class.
How would I actually do that? Introspector uses a bunch of private constructors to build it up so I can't really follow it, and simply returning an empty BeanInfo blows spring up. What does spring actually want with the beaninfo?
Any ideas?
Normally, when you provide an explicit BeanInfo, the Introspector will gather information automatically whenever the explicit BeanInfo returns null. So there should be no problem providing an empty BeanInfo that only returns a non-null BeanDescriptor to prohibit the automatic Customizer search.
For example:
import java.beans.*;
import java.util.stream.Stream;
public class BeanInfoTest {
public static void main(String... arg) throws IntrospectionException {
BeanInfo bi=Introspector.getBeanInfo(TheComponent.class, Object.class);
System.out.println("properties: ");
Stream.of(bi.getPropertyDescriptors())
.map(p->p.getPropertyType().getSimpleName()+' '+p.getName())
.forEach(System.out::println);
}
public static class TheComponent {
String foo;
int bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
}
public static class TheComponentBeanInfo extends SimpleBeanInfo {
/** Overridden to prevent the automated search for a Customizer */
#Override
public BeanDescriptor getBeanDescriptor() {
System.out.println("Providing my explicit BeanDescriptor");
return new BeanDescriptor(TheComponent.class);
}
}
}
will print
Providing my explicit BeanDescriptor
properties:
int bar
String foo
So it found the properties using automated search while using the explicit BeanDescriptor.

Aspect instantiation in AspectJ with pertypewithin

I'm trying to do a singleton pattern using AspectJ and the clause pertypewithin.
This is for educational purpose to fully understand the clause, i already did this using other techniques but i can't make it work as i wish.
package resourceManager;
//For every Type that extends resource
public aspect ResourcePool pertypewithin(resource+) {
//The resource
public Object cached;
Object around(Object instance): execution( *.new(..))&&!within(resource)&&this(instance){
if(cached==null)
{
proceed(instance);
cached=instance;
}
System.out.println(instance+" "+ cached);
return cached;
}
}
My problem is that at the end i return cached but the new object in my main function will hold the value of instance. Inside the aspect it behaves as it should: the first time i instantiate a resource, cached and instance will hold the same value, the secondo time, they will differ.
instance: resourceManager.RB#4ffac352 cached: resourceManager.RB#4ffac352
instance: resourceManager.RB#582d6583 cached: resourceManager.RB#4ffac352
But when i print the 2 new objects, this happens:
resourceManager.RB#4ffac352
resourceManager.RB#582d6583
I just found this old question today after it was edited lately.
What you want is a caching solution based on pertypewithin. While the idea is nice, there is one technical problem: You cannot return an object from an around() : execution(*.new(..)) advice because the object in question is not fully instantiated yet and the around advice implicitly returns void. Try for yourself and change the advice return type to void and do not return anything. It works - surprise, surprise! ;-)
So what can you do instead? Use around() : call(*.new(..)) instead in order to manipulate the result of a constructor call. You can even skip object creation altogether by not calling proceed() from there.
There are several ways to utilise this in order to make your resource objects cached singletons. But because you specifically asked for a pertypewithin use case, I am going to choose a solution involving this type of aspect instantiation. The drawback here is that you need to combine two aspects in order to achieve the desired outcome.
Sample resource classes:
package de.scrum_master.resource;
public class Foo {}
package de.scrum_master.resource;
public class Bar {}
Driver application creating multiple instances of each resource type:
package de.scrum_master.app;
import de.scrum_master.resource.Bar;
import de.scrum_master.resource.Foo;
public class Application {
public static void main(String[] args) {
System.out.println(new Foo());
System.out.println(new Foo());
System.out.println(new Bar());
System.out.println(new Bar());
}
}
Modified version of resource pool aspect:
package de.scrum_master.resourceManager;
public aspect ResourcePool pertypewithin(de.scrum_master.resource..*) {
private Object cached;
after(Object instance) : execution(*.new(..)) && this(instance) {
// Not necessary because SingletonAspect only proceeds for 'cache == null'
//if (cached != null) return;
cached = instance;
System.out.println("Cached instance = " + cached);
}
public Object getCachedInstance() {
return cached;
}
}
Aspect skipping object over object creation and returning cached objects:
package de.scrum_master.resourceManager;
public aspect SingletonAspect {
Object around() : call(de.scrum_master.resource..*.new(..)) {
Object cached = ResourcePool
.aspectOf(thisJoinPointStaticPart.getSignature().getDeclaringType())
.getCachedInstance();
return cached == null ? proceed() : cached;
}
}
Console log:
Cached instance = de.scrum_master.resource.Foo#5caf905d
de.scrum_master.resource.Foo#5caf905d
de.scrum_master.resource.Foo#5caf905d
Cached instance = de.scrum_master.resource.Bar#8efb846
de.scrum_master.resource.Bar#8efb846
de.scrum_master.resource.Bar#8efb846

Java Beans, BeanUtils, and the Boolean wrapper class

I'm using BeanUtils to manipulate Java objects created via JAXB, and I've run into an interesting issue. Sometimes, JAXB will create a Java object like this:
public class Bean {
protected Boolean happy;
public Boolean isHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
}
The following code works just fine:
Bean bean = new Bean();
BeanUtils.setProperty(bean, "happy", true);
However, attempting to get the happy property like so:
Bean bean = new Bean();
BeanUtils.getProperty(bean, "happy");
Results in this exception:
Exception in thread "main" java.lang.NoSuchMethodException: Property 'happy' has no getter method in class 'class Bean'
Changing everything to a primitive boolean allows both the set and get call to work. I don't have this option, however, since these are generated classes. I assume this happens because the Java Bean libraries only consider an is<name> method to represent a property if the return type is a primitive boolean, and not the wrapper type Boolean. Does anyone have a suggestion as to how to access properties like these through BeanUtils? Is there some kind of workaround I can use?
Finally I've found legal confirmation:
8.3.2 Boolean properties
In addition, for boolean properties, we allow a getter method to match the pattern:
public boolean is<PropertyName>();
From JavaBeans specification. Are you sure you haven't came across JAXB-131 bug?
Workaround to handle Boolean isFooBar() case with BeanUtils
Create new BeanIntrospector
private static class BooleanIntrospector implements BeanIntrospector{
#Override
public void introspect(IntrospectionContext icontext) throws IntrospectionException {
for (Method m : icontext.getTargetClass().getMethods()) {
if (m.getName().startsWith("is") && Boolean.class.equals(m.getReturnType())) {
String propertyName = getPropertyName(m);
PropertyDescriptor pd = icontext.getPropertyDescriptor(propertyName);
if (pd == null)
icontext.addPropertyDescriptor(new PropertyDescriptor(propertyName, m, getWriteMethod(icontext.getTargetClass(), propertyName)));
else if (pd.getReadMethod() == null)
pd.setReadMethod(m);
}
}
}
private String getPropertyName(Method m){
return WordUtils.uncapitalize(m.getName().substring(2, m.getName().length()));
}
private Method getWriteMethod(Class<?> clazz, String propertyName){
try {
return clazz.getMethod("get" + WordUtils.capitalize(propertyName));
} catch (NoSuchMethodException e) {
return null;
}
}
}
Register BooleanIntrospector:
BeanUtilsBean.getInstance().getPropertyUtils().addBeanIntrospector(new BooleanIntrospector());
you can just create second getter with SET - sufix as workaround :)

Categories