I've read documentation, but there is no definition of the main purpose of Dynamic Bean. I understand how to implement this but dont know why this approach so good.
So could someone tell the situation when it's good to use Dynamic Bean?
Thanks
Dynamic beans typically allow you to get and set fields which may not be explicit members. The most direct comparison is a map - maps allow you to get and set fields without defining them beforehand. However, a dyanamic bean conforms to standard java idioms (getters/setters).
Unlike a hashmap, however, dyanbeans can enforce constraints more readily (and they hide the underlying data structure implementation, so they can be lazy, or make data connections when being set, etc... ) . For example, you can easily add a getter or setter to your dynabean that is explicit, and the code would read very idiomatically and cleanly interact with other bean apis.
public int getCost()
{
if(this.get("cost")==null)
return -1;
return Integer.parseInt(super.get("cost"));
}
The most useful part about dynamic beans in ATG is providing additional DynamicPropertyMapper classes for classes that aren't already covered by it. First, note that you can use the DynamicBeans.setPropertyValue(object, property, value) and DynamicBeans.getPropertyValue(object, property) static methods to set or get properties on an object that don't necessarily correspond with Java bean properties. If the object you're using isn't registered with dynamic beans, it'll try to use Java bean properties by default. Support is provided out of the box to do that with repository items (properties correspond to repository item properties; also applies to the Profile object, naturally), DynamoHttpServletRequest objects (correspond to servlet parameters), maps/dictionaries (correspond to keys), and DOM Node objects (correspond to element attributes followed by the getters/setters of Node).
To add more classes to this, you need to create classes that extend DynamicPropertyMapper. For instance, suppose you want to make HttpSession objects work similarly using attributes with a fallback to the getters and setters of HttpSession. Then you'd implement the three methods from DynamicPropertyMapper, and the getBeanInfo(object) class can be easily implemented using DynamicBeans.getBeanInfo(object) if you don't have any custom BeanInfo or DynamicBeanInfo classes for the object you're implementing this for.
Once you have a DynamicPropertyMapper, you can register it with DynamicBeans.registerPropertyMapper(mapper). Normally this would be put into a static initialization block for the class you're writing the property mapper for. However, if you're making a property mapper for another class out of your control (like HttpSession), you'll want to make a globally-scoped generic service that simply calls the register method in its doStartService(). Then you can add that service to your initial services.
Related
Using MyBatis, I find myself having many mapper interfaces, e.g.
public interface BlogMapper {
#Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
Which are retrieved on demand using a MyBatis factory
final BlogMapper mapper = session.getMapper(BlogMapper.class);
Now, I'd like to allow constructor injection of those interfaces (implemented under the hood by MyBatis), so I cannot explicitly
container.addComponent(...);
What's the best way to accomplish this?
I suppose some kind of ComponentAdapter or ComponentMonitor would be the right pick.
You need a kind of custom factory for mybatis mapper instances and pico has ComponentAdapters API for this purpose. Check http://picocontainer.com/adapters.html and also the standard implementations if something is unclear. You will need to create Adapter instance per mapper, calling session.getMapper(Type) inside its getComponentInstance, thus encapsulating the special case for mapper instances creation.
This adapter instance should be added with container.addAdapter() method. If you don't want to do this manually each time, you need to leverage ComponentFactory, that will produce those ComponentAdapters.
Another way is to create higher level DAOs/Repos (one for each mapper), they will have mybatis SessionFactory injected, have a method for getting specific mapper and then delegate calls to the mapper with proper business grouping/validation/tx wrapping etc. Those higher level DAOs are added to the container to be injected into other components.
BTW. http://picocontainer.com/ has lot of interesting info hidden behind "View/Hide Sitemap Inline ..." link on the page top. Don't ask why :)
I am using Spring 3.2 and I am looking for a way that I can force controllers to specify which attributes allowed to be bound, so malicious users can not inject values into bound objects.
Spring recommends using setAllowedFields() to white-list / setDisallowedFields() to black-list.
Instead of doing manually this white-list, I want to do this dinamically, so I want to bound that attributes that are visible on the form.
So is it possible to get this white-list? Is there any way that I can get the visible attributes on the form?
Thanks.
You could implement a RequestDataValueProcessor especially the method processFormFieldValue. You could construct a collection of allowed field names, store this in the session.
Next you would extend the ConfigurableWebBindingInitializer and override the initBinder method. Which would retrieve the collection and pre-configure the WebDataBinder there.
And finally you would need some configuration to wire everything together.
Links
RequestDataValueProcessor javadoc
ConfigurableWebBindingInitializer javadoc
Looked at using CGLib, ASM, BCEL (aspect) and Javassist to add a field to a class during runtime....
Just to get my head straight it looks like these bytecode manipulators don't update the actual class rather allow the user to only dump the modification (like with CGLib and the writeFile method). Was hoping I would find a solution that (a) loaded the class (rather than doing an InputStream with BCEL) and (b) updated the class.
Maybe this is normal? Do people usually create a proxy and pass the proxy around?
What I want to do is to add a field (note: not a property via get/set methods) before passing the object along to a framework that looks for fields (not properties) with a particular annotation. So "clients" are creating my target classes that I want to inject with an extra field. Intercepting with AOP calls to a service layer where I want to manipulate these objects.
You can redefine classes with Intrumentation. However a common limiation is that you cannot change the fields used. This is because you cannot change the contents of a object (or add to it) once it has been created.
In your case you can,
create a proxy as you suggest, however proxies need to be interfaces.
create a subclass which has the additional field(s)
add the field before the class has loaded.
I am using Struts 2 and Spring autowiring. Right now, the default strategy is set to by-name, but usually we use the constructor and the fallback works to autowire in properties when only one implementing class is available.
There is one property however that I'd like to wire into an action class that has several implementing classes, so I made the Action a java bean, with the properties as fields that can be set. Unfortunately, the only ways that these will be used (apparently) is if they have a public getter/setter, which also exposes them to the type converter at request time. In other words, if a client adds their name to the request as form fields or parameters, Struts will attempt to write those values to them.
So my question is, is it actually possible to use by-name autowiring without exposing properties like that (which may or may not be a security hazard), or am I better off just using XML and defining the Action as an object with scope prototype?
I did eventually track down the documentation for the ParametersInterceptor which actually lists three ways you can limit what parameters are set by the interceptor.
Configuring excludeParams in the parameter configuration, which is a global regex which applies to all actions (not what I want, also possibly deprecated as it is no longer described in the most recent class docs).
Setting excludeMethods (does the same as the previous, the preferred method for global excludes)
Implementing ParameterNameAware, which is the closest to what I wanted. Here you can whitelist what parameters are used.
In the end, defining the action as a prototype object in the normal Spring configuration seemed to be the most prudent. Letting the action manage what parameters it has means another place where parameters need to be explicitly white listed every time a change is made.
For the sake of my own education, I wanted to build a simple Dependency Injection framework that functions similar to the way Google's Guice does. So that when a class is loaded, it pre-populates annotated fields with data from a factory class.
I am using Reflections to scan all my factory classes at compile time and save those classes in a static list so that when it comes time to load my classes, I have a reference to my factories that I can then scan methods and return the appropriate data.
Where i'm stuck at is how to pre-populate my classes annotated fields without actually doing any of the work in the actual class. In other words, when a class is loaded, I need to be able to determine if any of the fields are annotated with a specific annotation, and if they are, retrieve the value from the factory class.
Is there some way of performing reflection on a class right before it is loaded, pre-populate specific fields and then return an instance of that class to be used?
I could extend all of my classes that require dependency injection with a base class that does all of this work, but I figure there must be a better way so that I can simply use an #Inject (or whatever annotation I decide to use to say that this field requires DI) and "magically" all the work is done.
The way that Guice approaches this is that it will only populate the fields of an instance that was itself created by Guice1. The injector, after creating the instance, can use the Reflection API to look at the fields of the Class and inspect their annotations with Field.getDeclaredAnnotations().
This is also the reason why, when you want to inject into a static field, you need to use Binder.requestStaticInjection() to populate the static fields.
Guice does not simply scan your code for annotations; all injections recurse from an explicit request (e.g. requestStaticInjection(), Injector.getInstance(), etc). Now often that initial, explicit request will have been made in some library code.
For example, if you're using guice-servlet you let Guice create the instances of your servlet by using the serve().with() calls. But if you didn't do that, and instead left your servlet config in your web.xml, Guice would not inject into your servlet.
1 - You can also request explicit injection using Binder.requestInjection().