I have a visibility problem in projects, once my implementation is not visible as my interface. The visibility problem can not be solved.
I thought of a solution:
I wrote a note
#Target (ElementType.TYPE)
#Retention (RetentionPolicy.RUNTIME)
public #interface Register {
}
I use it in classes
#Register
public class ClientAlteracaoObserver implements Complement <ClientGestaoValue>, IClienteAlteracaoObserver {
}
I create an engine at project initialization that records in a container the implementations and interfaces
public class Injection implements ServletContextListener {
#Override
public void contextDestroyed( ServletContextEvent arg0 ) {
}
#Override
public void contextInitialized( ServletContextEvent arg0 ) {
System.out.println( "Agora as coisas vão ficar boas!!!!" );
Container container = Container.getInstance();
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( true );
scanner.addIncludeFilter( new AnnotationTypeFilter( Register.class ) );
Set< BeanDefinition > registers = scanner.findCandidateComponents( "br.com.syonet" );
for ( BeanDefinition bd : registers ) {
try {
Class< ? > clazz = Class.forName( bd.getBeanClassName() );
List< Class< ? > > interfaces = Arrays.asList( clazz.getInterfaces() );
for ( Class< ? > contract : interfaces ) {
container.register( contract, clazz );
}
} catch ( Exception e ) {
e.printStackTrace();
}
}
System.out.println( "GG garotão!" );
}
}
my container
public class Container {
private static final Container instance = new Container();
private final HashMap< String, Object> intances = new HashMap<>();
private Container() { }
public static Container getInstance() {
return instance;
}
public void register( Class<?> contract, Class<?> contractImpl ) throws InstantiationException, IllegalAccessException {
this.intances.put( contract.getName(), contractImpl.newInstance() );
}
#SuppressWarnings("unchecked")
public <T> T get( Class<T> interfac ) {
return ( T ) this.intances.get( interfac.getName() );
}
public static <T> T load( Class<T> interfac ) {
return ( T ) instance.get( interfac );
}
}
And finally I use this way:
class Test {
private IClienteAlteracaoObserver observer = Container.load(IClienteAlteracaoObserver.class);
}
But I would like to create the annotation #Inject to do the work of Container.load(IClienteAlteracaoObserver.class);
class Test {
private #Inject IClienteAlteracaoObserver observer;
}
While what you want is possible, I would not recommend it. Annotations are primarily meta-information, mostly processed at compile-time. For this, one writes an annotation processor, which must be passed to the compiler so it can process the annotations. Baeldung has a nice tutorial on annotation processing in which a simple builder is created through an annotation processor.
I propose an alternative in form of a static final variable:
public Class Test {
public static final String DEFAULT_FIELD_VALUE = "example";
private String field; // to ensure encapsulation, all attributes should be private
public Test() {
this(DEFAULT_FIELD_VALUE);
}
public Test(String field) {
this.field = field;
}
public String getField() {
return this.field;
}
public static void main(String... args) {
System.out.println(new Test().getField().equals("example"));
}
}
(Ideone live demo)
You can couple this approach with a static-block to make the configuration more flexible, by e.g. reading the default values from system variables or a config file.
If your objects start to become more complex, you can look at the Builder pattern for a more flexible solution.
A remark on your code: Due to data encapsulation, you do not want your class attributes accessible directly from the outside. Thus you should not set them public. Instead, write mutator methods.
Related
Would be grateful if you could help me with the following.
Suppose I have the following classes and interface:
public interface BaseType {
public void method();
}
#Component
#Scope(SCOPE_PROTOTYPE)
public class BaseTypeImpl implements BaseType {
private int num;
public BaseTypeImpl(int num) {
this.num = num;
}
#Override
public void method() {
System.out.println(num);
}
}
#Component
#Scope(SCOPE_PROTOTYPE)
public class ChildBaseTypeImpl extends BaseTypeImpl {
String mes;
public ChildBaseTypeImpl(int num, String mes) {
super(num);
this.mes = mes;
}
#Override
public void method() {
super.method();
System.out.println(mes);
}
}
#Component
#Scope(SCOPE_PROTOTYPE)
public class SecondaryTypeImpl implements BaseType {
private String str;
public SecondaryTypeImpl(String str) {
this.str = str;
}
#Override
public void method() {
System.out.println(str);
}
}
In result, I have 3 classes implementing 1 interface.
All the classes have non-default constructor with a different parameters.
Is there a way to make Spring lookup for a correct bean by BaseType interface based on the constructor parameters?
I want to do this:
ApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml");
ctx.getBean(BaseType.class, 11); //Should return instance of BaseTypeImpl class object, since it has constructor taking int
or like this:
ctx.getBean(BaseType.class, 11, "hello!"); //Should return instance of ChildBaseTypeImpl
Trying to do this will result in exception:
Exception in thread "main"
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No
qualifying bean of type 'springtest.BaseType' available: expected
single matching bean but found 3:
baseTypeImpl,childBaseTypeImpl,secondaryTypeImpl
It seems like there is no straightforward way to do this.
But maybe is it possible to get all classes, that are assignable from a BaseType, find appropriate constructors among them and then call getBean method with the *Impl class as a first parameter?
UPDATED
Thanks everyone for answering!
As pvpkiran mentioned, there is a way to get class of bean by bean name.
This opens the door for reflection, which solves the problem, here's the sample code:
public class App {
static ApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml");
public static void main(String[] args) {
BaseType beanByInterface = getBeanByInterface(BaseType.class, "Hello!");
System.out.println(beanByInterface.getClass());
}
public static <T> T getBeanByInterface(Class<T> interf, Object... params) {
BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr);
TypeFilter tf = new AssignableTypeFilter(interf);
s.addIncludeFilter(tf);
s.scan("springtest"); //Sample project package name
String[] beans = bdr.getBeanDefinitionNames();
for(String b : beans) {
Class<?> type = ctx.getType(b);
MAIN: for(Constructor cons : type.getConstructors()) {
if (cons.getParameterCount() == params.length) {
for (int i = 0; i < cons.getParameterCount(); i++) {
if (!params[i].getClass().equals(cons.getParameterTypes()[i])) { //Will fail comparing primitive and boxed types, just leaving like this for simplicity
continue MAIN;
}
}
return (T) ctx.getBean(type, params);
}
}
}
return null;
}
}
The code is buggy, but this is just to show the concept.
Having the beans classes I can get the right bean, that has the needed constructor.
This sample outputs "class springtest.SecondaryTypeImpl"
But I believe this should be the common problem that is covered in some utils.
I don't want to invent the bicycle, but still can't find the solution.
UPDATED 2
Seems like there is no such solution in existing libs, since it's not the best practice.
Anyway, here's the updated method, maybe someone will find it useful.
public static <T> T getBeanByInterface(Class<T> interf, Object... params) {
String[] beans = ctx.getBeanNamesForType(interf);
for(String beanName : ctx.getBeanNamesForType(interf)) {
Class<?> type = ctx.getType(beanName);
Class<?>[] paramTypes = new Class[params.length];
//Getting params types
for (int i = 0; i < params.length; i++) {
paramTypes[i] = params[i].getClass();
}
if (ConstructorUtils.getMatchingAccessibleConstructor(type, paramTypes) != null) {
return (T) ctx.getBean(type, params);
}
}
return null;
}
BeanFactory has following getBean() declaration
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException
As you can see here, there is no declaration for class type, bean name and arguments(which is what you are looking for).
But you can get the bean using bean name and arguments.
ApplicationContext ctx = new FileSystemXmlApplicationContext("beans.xml");
ChildBaseTypeImpl childBaseTypeImpl = (ChildBaseTypeImpl) ctx.getBean("childBaseTypeImpl", 11, "hello");
BaseTypeImpl basetypeImpl = (BaseTypeImpl) ctx.getBean("baseTypeImpl", 11, );
Well, you can't use constructor arguments to differentiate your beans, as #alexlys noted. But you could do something different with the same result. Both approaches assumes that you could define what bean you need not in runtime but when you write the code.
You could create beans with unique names and then get desired bean by
name, not by interface
You could add some marker interfaces like
interface SecondaryType extends BaseType {//empty}. Each bean will implement only one specific interface so you could instaniate beans using such iterfaces.
I have a lot of actions. All actions works with some Object/Context that passed in all actions. I want to use pattern Strategy/Policy.
Here is examples in Kotlin:
interface Action {
val name: String
fun run(ctx: Context)
}
class Multiply: Action {
override name = "MULTIPLY"
override fun run(ctx: Context) {
writeToDb(ctx.id, ctx.number * 2)
}
}
class Substract
class SendNotification
etc...
So I want to register all strategies on startup. And select strategy from structure like Enum.
val action = selectAwaitingAction()
val ctx = selectCtxById(action.transaction_id)
perfromAction(ctx, actions.getByName(action.name))
fun performAction(ctx Context, action: Action) {
action.run(ctx)
}
My question is how register strategy by interface type?
Note: This is complete example. If you are looking only for automatic registration by interface type, scroll to last part of answer.
Strategy design pattern can be implemented using function tables. This stores implementations in Map<String,IImpl> where key is name of algorithm and value is concrete implementation of algorithm .
Common approach:
Consider class Context holding all parameters shared between imlementations of interface Solver.
public class Context extends HashMap<String,Object> {
public <T> T get(String key, Class<T> resultClass){
return resultClass.cast(get(key));
}
public <T> T getOrDefault(String key, T def, Class<T> resultClass){
return resultClass.cast(getOrDefault(key,def));
}
}
And interface Solver with required methods solve and name
public interface Solver {
void solve(Context context);
String name();
}
Then you can create implementations of Solver interface modifying shared Context object. I have created AddSolver and MultiplySolver in this example.
AddSolver.java:
public class AddSolver implements Solver {
#Override
public void solve(Context context) {
context.put("result", context.getOrDefault("result",0.0, Double.class) + context.get("add", Double.class));
}
#Override
public String name() {
return "+";
}
}
MultiplySolver.java
public class MultiplySolver implements Solver {
#Override
public void solve(Context context) {
context.put("result", context.getOrDefault("result",0.0, Double.class) * context.get("multiply", Double.class));
}
#Override
public String name() {
return "*";
}
}
Manual construction of Map<String,Solver>:
Implementations of interface Solver can be stored in HashMap<String,Solver>
#Test
public void testCustomFunctionMap(){
HashMap<String,Solver> functionMap = new HashMap<>();
functionMap.put("+", new AddSolver());
functionMap.put("*", new MultiplySolver());
Context context = new Context();
context.put("add", 2.0);
functionMap.get("+").solve(context);
TestCase.assertEquals(2.0, context.get("result", Double.class));
context.put("multiply", 3.0);
functionMap.get("*").solve(context);
TestCase.assertEquals(6.0, context.get("result", Double.class));
}
Automatic construction of Map<String,Solver>
There is more approaches, if you need costruct Map<String,Solver> automatically. A lot of them is mentioned in this question. I have used org.reflections library.
public class SolverScanner{
static HashMap<String, Solver> functionMap;
static {
functionMap = new HashMap<>();
Reflections reflections = new Reflections(SolverScanner.class.getPackage().getName());
for( Class<? extends Solver> clazz : reflections.getSubTypesOf(Solver.class)){
try {
Solver solver = clazz.newInstance();
functionMap.put(solver.name(), solver);
} catch (Exception e) {
throw new IllegalStateException("Cannot construct functionMap",e);
}
}
}
public static HashMap<String, Solver> getFunctionMap(){
return functionMap;
}
private SolverScanner(){}//disable instantiating
}
And usage:
#Test
public void testSolverScannerFunctionMap(){
HashMap<String,Solver> functionMap = SolverScanner.getFunctionMap();
Context context = new Context();
context.put("add", 2.0);
functionMap.get("+").solve(context);
TestCase.assertEquals(2.0, context.get("result", Double.class));
context.put("multiply", 3.0);
functionMap.get("*").solve(context);
TestCase.assertEquals(6.0, context.get("result", Double.class));
}
I have written simple container that registers a class and it's interface and has a method to create object from that information like this:
public class DIContainer {
protected static DIContainer instance;
protected Hashtable<Class<?>, Class<?>> classMap;
protected DIContainer(){
this.classMap = new Hashtable<Class<?>, Class<?>>();
}
public static DIContainer getInstance(){
if (DIContainer.instance == null)
DIContainer.instance = new DIContainer();
return DIContainer.instance;
}
public void regClass(Class<?> interf, Class<?> classToReg){
this.classMap.put(interf, classToReg);
}
public Object create(Class<?> interf) throws Exception{
if(!this.classMap.containsKey(interf))
throw new Exception("No such class registered with "+interf.getName()+" interface");
return this.classMap.get(interf).newInstance();
}
}
But I want before creating new instance to bypass it to proxy, for it to create, so I have this proxy class:
public class MyProxy implements InvocationHandler
{
private Map map;
private Object obj;
public static Object newInstance(Map map, Object obj, Class[] interfaces)
{
return Proxy.newProxyInstance(map.getClass().getClassLoader(),
interfaces,
new MyProxy(map, obj));
}
public MyProxy(Map map, Object obj)
{
this.map = map;
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args) throws
Throwable
{
try {
return m.invoke(obj, args);
} catch (NoSuchMethodError e)
{
//Object result;
String methodName = m.getName();
if (methodName.startsWith("get"))
{
String name = methodName.substring(methodName.indexOf("get")+3);
return map.get(name);
}
else if (methodName.startsWith("set"))
{
String name = methodName.substring(methodName.indexOf("set")+3);
map.put(name, args[0]);
return null;
}
else if (methodName.startsWith("is"))
{
String name = methodName.substring(methodName.indexOf("is")+2);
return(map.get(name));
}
return null;
}
}
}
But for proxy class I need to provide type of class and it's interface, but I only have it's information with X.class. Can get the type (for example if it's class X) X, when I have X.class? Maybe I'm doing this the wrong way and I need to change something in order for it to work, but right now I figured I need to get that class type, so then I could provide it for proxy?
Because if I would right something like this:
X.class x;
I would get error. So I need to write like this X x;, but I only have X.class
Update:
To explain it simply, is it possible to get this:
X obj;
when you only have X.class (with X.class.newInstance it would instantiate it (like with new?), but I need not instantiated obj yet).
Update2
I tried this:
Object x = (Object) MyProxy.newInstance(map, this.classMap.get(interf).newInstance(), new Class[] {this.classMap.get(interf)});
But then I get this error:
Exception in thread "main" java.lang.IllegalArgumentException: class lab.X is not visible from class loader
My class X looks like this:
public class X implements I{
String name;
X(){}
#Override
public String getName() {
return name;
}
#Override
public void setName(String name) {
this.name = name;
}
}
and it's interface looks like this:
public interface I {
public String getName();
public void setName(String name);
}
If I understand correctly, you are trying to instantiate an element of the class X.class? If that is the case, all you need to do is call X.class.newInstance().
java.lang.IllegalArgumentException: class lab.X is not visible from
class loader
Isn't this error message quite clear? You need to make sure that the same class loader is being used.
In here:
public static Object newInstance(Map map, Object obj, Class[] interfaces)
{
return Proxy.newProxyInstance(map.getClass().getClassLoader(),
interfaces,
new MyProxy(map, obj));
}
you shouldn't be using the class loader of the map, I'd think you should use class loader of the target object or pass the proper class loader as a separate argument.
I think there are other problems in your approach as well, such as not synchronizing your container creation and not using generics for your proxy type.
For the first part, class DIContainer, it would be better to use:
protected final Map<Class<?>, Class<?>> classMap;
protected DIContainer() {
classMap = Collections.synchronizedMap(new HashMap<Class<?>, Class<?>>());
}
public <I> void regClass(Class<I> interf, Class<? extends I> classToReg) {
this.classMap.put(interf, classToReg);
}
public <T> T create(Class<T> interf) throws Exception {
Class<?> implClass = classMap.get(interf);
if (implClass == null) {
throw new Exception("No such class registered with " + interf.getName()
+ " interface");
}
Constructor<?> c = implClass.getConstructor();
c.setAccessible(true); // If default constructor not public
return interf.cast(c.newInstance());
}
Safe typing, though still partly at run-time.
More or less obsolete Hashtable replaced by equivalent
Calling newInstance on the class bypasses exceptions thrown on getting the default constructor and doing that one's newInstance.
The second part of the question: I fail to understand it; the interface class(es) is what is proxied. In the create above you could easily proxy Class<T> and yield a (seemingly) T object. And you could delegate in the proxy class to an T object created as in the create above.
I need some kind of Converter-Mapper and don't come up with any good idea, how to easily attach an enum with an special converter. I tried the following:
//ConverterInterface:
public interface PropertyConverter<T>
{
public String convertObjectToString( T object );
public T convertStringToObject( String string );
}
//Concrete Converter
public class FooConverter implements PropertyConverter<Foo>
{
#Override
public String convertObjectToString( Foo object )
{
throw new UnsupportedOperationException( "Not implemented yet." );
}
#Override
public Foo convertStringToObject( String string )
{
throw new UnsupportedOperationException( "Not implemented yet." );
}
}
//Dataclass
public class Foo
{
}
Same goes for Boo, and here the enum, where I want to attach the Converter to a specific type:
public enum PropEnum
{
BOO(new BooConverter()),
FOO(new FooConverter());
PropertyConverter<?> converter;
private PropEnum( PropertyConverter<?> converter )
{
this.converter = converter;
}
public PropertyConverter<?> getConverter()
{
return converter;
}
}
But since my PropertyConverter uses a Wildcard, I only get Object To String, and String To Object Methods instead of concrete types, like Foo To String and String To Foo, when I use it like the following:
Is there any way to receive the concrete type from the converter implementation?
TLDR: I'd like to know how to extend fit.TypeAdaptor so that I can invoke a method that expects parameters as default implementation of TypeAdaptor invokes the binded (bound ?) method by reflection and assumes it's a no-param method...
Longer version -
I'm using fit to build a test harness for my system (a service that returns a sorted list of custom objects). In order to verify the system, I thought I'd use fit.RowFixture to assert attributes of the list items.
Since RowFixture expects the data to be either a public attribute or a public method, I thought of using a wrapper over my custom object (say InstanceWrapper) - I also tried to implement the suggestion given in this previous thread about formatting data in RowFixture.
The trouble is that my custom object has around 41 attributes and I'd like to provide testers with the option of choosing which attributes they want to verify in this RowFixture. Plus, unless I dynamically add fields/methods to my InstanceWrapper class, how will RowFixture invoke either of my getters since both expect the attribute name to be passed as a param (code copied below) ?
I extended RowFixture to bind on my method but I'm not sure how to extend TypeAdaptor so that it invokes with the attr name..
Any suggestions ?
public class InstanceWrapper {
private Instance instance;
private Map<String, Object> attrs;
public int index;
public InstanceWrapper() {
super();
}
public InstanceWrapper(Instance instance) {
this.instance = instance;
init(); // initialise map
}
private void init() {
attrs = new HashMap<String, Object>();
String attrName;
for (AttrDef attrDef : instance.getModelDef().getAttrDefs()) {
attrName = attrDef.getAttrName();
attrs.put(attrName, instance.getChildScalar(attrName));
}
}
public String getAttribute(String attr) {
return attrs.get(attr).toString();
}
public String description(String attribute) {
return instance.getChildScalar(attribute).toString();
}
}
public class MyDisplayRules extends fit.RowFixture {
#Override
public Object[] query() {
List<Instance> list = PHEFixture.hierarchyList;
return convertInstances(list);
}
private Object[] convertInstances(List<Instance> instances) {
Object[] objects = new Object[instances.size()];
InstanceWrapper wrapper;
int index = 0;
for (Instance instance : instances) {
wrapper = new InstanceWrapper(instance);
wrapper.index = index;
objects[index++] = wrapper;
}
return objects;
}
#Override
public Class getTargetClass() {
return InstanceWrapper.class;
}
#Override
public Object parse(String s, Class type) throws Exception {
return super.parse(s, type);
}
#Override
protected void bind(Parse heads) {
columnBindings = new TypeAdapter[heads.size()];
for (int i = 0; heads != null; i++, heads = heads.more) {
String name = heads.text();
String suffix = "()";
try {
if (name.equals("")) {
columnBindings[i] = null;
} else if (name.endsWith(suffix)) {
columnBindings[i] = bindMethod("description", name.substring(0, name.length()
- suffix.length()));
} else {
columnBindings[i] = bindField(name);
}
} catch (Exception e) {
exception(heads, e);
}
}
}
protected TypeAdapter bindMethod(String name, String attribute) throws Exception {
Class partypes[] = new Class[1];
partypes[0] = String.class;
return PHETypeAdaptor.on(this, getTargetClass().getMethod("getAttribute", partypes), attribute);
}
}
For what it's worth, here's how I eventually worked around the problem:
I created a custom TypeAdapter (extending TypeAdapter) with the additional public attribute (String) attrName. Also:
#Override
public Object invoke() throws IllegalAccessException, InvocationTargetException {
if ("getAttribute".equals(method.getName())) {
Object params[] = { attrName };
return method.invoke(target, params);
} else {
return super.invoke();
}
}
Then I extended fit.RowFixture and made the following overrides:
public getTargetClass() - to return my class reference
protected TypeAdapter bindField(String name) throws Exception - this is a protected method in ColumnFixture which I modified so that it would use my class's getter method:
#Override
protected TypeAdapter bindField(String name) throws Exception {
String fieldName = camel(name);
// for all attributes, use method getAttribute(String)
Class methodParams[] = new Class[1];
methodParams[0] = String.class;
TypeAdapter a = TypeAdapter.on(this, getTargetClass().getMethod("getAttribute", methodParams));
PHETypeAdapter pheAdapter = new PHETypeAdapter(fieldName);
pheAdapter.target = a.target;
pheAdapter.fixture = a.fixture;
pheAdapter.field = a.field;
pheAdapter.method = a.method;
pheAdapter.type = a.type;
return pheAdapter;
}
I know this is not a neat solution, but it was the best I could come up with. Maybe I'll get some better solutions here :-)