How to get this.getClass().getConstructor of a super class? - java

Is there a way for me to get a super implementation directly through getContructor? I want to call the constructor on "this class or any superclass".
The scenario details are that I have a base class that builds its data using reflection but the data is coming in from an external file. The external loader has a lookup that checks to see if data exists for a particular class and all of that is wrapped into ImplementedCard, below.
This works fine (enough) and isn't directly related to the question aside from my needing to be able to create all of these instances starting from an ImplementedCard instance:
public class Card implements DeepCopyable<Card> {
protected ImplementedCardList.ImplementedCard implementedCard;
public Card() {
this.implementedCard = ImplementedCardList.getInstance().getCardForClass(this.getClass());
this.initFromImplementedCard(this.implementedCard);
}
public Card(ImplementedCardList.ImplementedCard implementedCard) {
this.implementedCard = implementedCard;
this.initFromImplementedCard(this.implementedCard);
}
public void initFromImplementedCard(ImplementedCardList.ImplementedCard implementedCard) {
if (implementedCard != null) {
this.name_ = implementedCard.name_;
/* ... and so on */
}
}
// This deepCopy pattern is required because we use the class of each card to recreate it under certain circumstances
#Override
public Card deepCopy() {
Card copy = null;
try {
try {
copy = this.getClass().getConstructor(ImplementedCardList.ImplementedCard.class).newInstance(this.implementedCard);
} catch(NoSuchMethodException e) {
if(!this.getClass().equals(TestHero.class)) {
log.warn(this.getClass().toString() + " is missing ImplementedCard constructor");
}
copy = getClass().newInstance();
} catch(InvocationTargetException e) {
log.error("InvocationTargetException error", e);
copy = getClass().newInstance();
}
} catch(InstantiationException e) {
log.error("instantiation error", e);
} catch(IllegalAccessException e) {
log.error("illegal access error", e);
}
if (copy == null) {
throw new RuntimeException("unable to instantiate card.");
}
copy.name_ = this.name_;
/* ... and so on */
return copy;
}
}
This base class is then extended like so:
public class Minion extends Card implements CardEndTurnInterface, CardStartTurnInterface {
public Minion() {
super();
}
public Minion(ImplementedCardList.ImplementedCard implementedCard) {
super(implementedCard);
}
#Override
public void initFromImplementedCard(ImplementedCardList.ImplementedCard implementedCard) {
if (implementedCard != null) {
super.initFromImplementedCard(implementedCard);
/* custom init goes here */
}
}
/* other class details follow */
}
public abstract class Hero extends Minion implements MinionSummonedInterface {
public Hero() {
super();
}
public Hero(ImplementedCardList.ImplementedCard implementedCard) {
super(implementedCard);
}
/* no custom init; other class details follow */
}
public class Hunter extends Hero {
public Hunter() {
super();
}
public Hunter(ImplementedCardList.ImplementedCard implementedCard) {
super(implementedCard);
}
/* no custom init; other class details follow */
}
This goes on for hundreds of classes. What I want to do is pull out the constructors that do nothing but call super with the same parameters but when I do, it breaks the getConstructor call in deepCopy.

For each class, you can do:
Hero h = new Hero();
Class hc = h.getClass();
// Get super class and its constructor.
Class<?> sc = hc.getSuperclass();
Constructor scConst = sc.getConstructor(ImplementedCard.class);
// Get super class's parent and its constructor.
Class<?> ssc = sc.getSuperclass();
Constructor sscConst = ssc.getConstructor(ImplementedCard.class);
You could also put this in a loop until you get to Object.class or some other point in the class hierarchy where you'd like to break.

As #nhylated suggested, try
this.getClass().getSuperClass()
Here is a nice explanation regarding why
super.getClass()
behaves like it does.

Related

How to reduce code duplication when using non-compatible wrappers

[TL;DR]
The problem is, in AWrapper and AType I have to duplicate pretty much whole function, where there is always the syntax:
public [TYPE/void] METHOD([OPT: args]) throws TestFailedException {
[OPT: TYPE result = null;]
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
[OPT: result =] ((WrappedType) element).METHOD([OPT: args]);
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
[OPT: return result;]
}
Lets say I have 2 classes I don't own:
public class IDontOwnThisType {
public void doA(String string) { System.out.println("doA"); }
public String doB(); {System.out.println("doB"); return "doB";}
public OtherTypeIDoNotOwn doC() {System.out.println("doC"); return new OtherTypeIDoNotOwn();}
}
public OtherTypeIDoNotOwn {
public void doD() { System.out.println("doD"); }
public String doE() { System.out.println("doE); }
public OtherTypeIDoNotOwn doF(String string) {System.out.println("doF"); return new OtherTypeIDoNotOwn();}
}
So, I have an interface:
public interface OperationManipulator {
void beforeOperation(); //called before operation
void handleSuccess(); //called after success
void handleSoftFailure(Exception e); //called after every failure in every try
void handleFailure(Exception e) throws TestFailedException; //called after reaching time limit
}
Then interface that extends above one, "mimicking" methods of external classes, but throwing custom exception:
public interface IWrapper<T extends IType> extends OperationManipulator {
public void doA(String string) throws TestFailedException;
public String doB() throws TestFailedException;
public T doC() throws TestFailedException;
}
Then we have IType, which also extends OperationManipulator:
public interface IType<T extends IType> extends OperationManipulator {
public void doD() throws TestFailedException;
public String doE() throws TestFailedException;
public T doF(String string) throws TestFailedException;
}
Then, we have abstract implementations of above interfaces:
public abstract class AType<T extends IType> implements IType{
Object element; // I do not own type of this object, cant modify it.
Class typeClass;
long TIMEOUT = 5000;
long WAIT_FOR_NEXT_TRY = 100;
public AType(Object element) {
this.element = element;
elementClass = this.getClass();
}
/* ... */
}
Then, we override functions from the interfaces, excluding OperationManipulator interface:
Function not returning anything version:
#Override
public void doD() throws TestFailedException {
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
((OtherTypeIDoNotOwn) element).doD();
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
Function returning normal reference version:
#Override
public String doE() throws TestFailedException {
String result = null;
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
result = ((OtherTypeIDoNotOwn) element).doE();
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
return result;
}
And function returning object of type parameter:
#Override
public T doF(String string) throws TestFailedException {
T result = null;
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
OtherTypeIDoNotOwn temp = ((OtherTypeIDoNotOwn) element).doF(string);
result = (T) elementClass.getDeclaredConstructor(Object.class).newInstance(temp);
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
return result;
}
The same goes for AWrapper, but the differences are:
constructor have class argument of stored type
object is cast to IDoNotOwnThisType instead of OtherTypeIDoNotOwn. Functions of this object also may return OtherTypeIDoNotOwn.
IDoNotOwnThisType is type that AWrapper is wrapping.
OtherTypeIDoNotOwn is type that AType is wrapping.
Then, we have implementation of these abstract classes:
public class AssertingType extends AType<AssertingType> {
public AssertingType(Object element) {
super(element);
}
#Override
public void beforeOperation() {
//System.out.println("Asserting type before operation!");
}
#Override
public void handleSuccess() {
//TODO: add to log file and log to output
System.out.println("Asserting type success!");
}
#Override
public void handleFailure(Exception e) throws TestFailedException {
//TODO: add to log file, log to output and throw exception
System.out.println("Asserting type failure!");
e.printStackTrace();
throw new TestFailedException();
}
#Override
public void handleSoftFailure(Exception e) {
//TODO: add to log file, log to output
System.out.println("Asserting type soft failure!");
e.printStackTrace();
}
}
And:
public class AssertingWrapper extends AWrapper<AssertingType> {
public AssertingWrapper (Object driver) {
super(driver, AssertingType.class);
}
#Override
public void beforeOperation() {
//TODO
System.out.println("Asserting wrapper success!");
}
#Override
public void handleSuccess() {
//TODO: add to log file and log to output
System.out.println("Asserting wrapper success!");
}
#Override
public void handleFailure(Exception e) throws TestFailedException {
//TODO: add to log file, log to output and throw exception
System.out.println("Asserting wrapper failure!");
throw new TestFailedException();
}
#Override
public void handleSoftFailure(Exception e) {
//TODO: add to log file, log to output
System.out.println("Asserting wrapper soft failure!");
e.printStackTrace();
}
}
So, we can use it like that:
AssertingWrapper wrapper = new AssertingWrapper(new IDoNotOwnThisType());
AssertingType type = wrapper.doC();
AssertingType type2 = type.doF();
Output:
Asserting wrapper before operation!
doC
Asserting wrapper success!
Asserting type before operation!
doF
Asserting type success!
The full working code is here:
LIVE
The problem is, I have always to write while, try catch etc in AType and AWrapper, can I somehow reduce code duplication? In the example i provided just 3 functions per class, but in my real code I have 50+ methods. Can I somehow wrap these functions so thepart that is repeating is not duplicated?
Your problem appears to be quite complicated, and I cannot claim to have been able to successfully wrap my mind around it, but I will give it a try, because it appears to be a very interesting problem and because I happen to have some experience in dealing with situations that yours appears similar to.
Please excuse me if my answer turns out to be completely off the mark due to a misunderstanding on my part.
So, what it appears that you are looking for is a general purpose solution for injecting your own code before and after an invocation where the invocation may be to any method, accepting any number of parameters, and returning any kind of return value.
In java there exists a dynamic proxy facility, which you can find under java.lang.reflect.Proxy.
With it, you can do the following:
ClassLoader classLoader = myInterfaceClass.getClassLoader();
T temp = (T)Proxy.newProxyInstance( classLoader, new Class<?>[] { myInterfaceClass },
invocationHandler );
The invocationHandler is supplied by you, and it is of the following form:
private final InvocationHandler invocationHandler = new InvocationHandler()
{
#Override
public Object invoke( Object proxy, Method method, Object[] arguments )
throws Throwable
{
/* your pre-invocation code goes here */
/* ... */
/* invoke original object */
Object result = method.invoke( myObject, arguments );
/* your post-invocation code goes here */
/* ... */
/* return the result (will probably be null if method was void) */
return result;
}
};
So, I think you might be able to use that to solve your problem with the minimum amount of code.
Neither the creation of a dynamic proxy nor the call to method.invoke() perform terribly well, (you know, reflection is somewhat slow,) but if you are using it for testing, it should not matter.

Convert Android code fragment from Java to C# ("inline class extension")

I am trying to convert an Android Library from Java to C# (Xamarin).
Take a look at this definition of a private field in the class:
private SimpleOnGestureListener longClickListener = new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
hasPerformedLongPress = childView.performLongClick();
if (hasPerformedLongPress) {
if (rippleHover) {
startRipple(null);
}
cancelPressedEvent();
}
}
#Override
public boolean onDown(MotionEvent e) {
hasPerformedLongPress = false;
return super.onDown(e);
}
};
As far as I know there is no way in C# to create an "inline extension" of a class.
How would you convert this piece of code ? Keep in mind that "hasPerformedLongPress" and "rippleHover" are private fields of the class.
You can create a new private class which implements the interface - you can access the fields of the outer class via the 'outerInstance' field of the inner class. However, the only way I can make this work is to change the 'longClickListener' field to a local variable in order to be able to pass 'this' to the new private class constructor - since you can't use 'this' from a C# field definition:
internal class test
{
private bool rippleHover;
private bool hasPerformedLongPress;
internal virtual void method()
{
SimpleOnGestureListener longClickListener = new SimpleOnGestureListenerAnonymousInnerClassHelper(this);
}
private class SimpleOnGestureListenerAnonymousInnerClassHelper : GestureDetector.SimpleOnGestureListener
{
private readonly test outerInstance;
public SimpleOnGestureListenerAnonymousInnerClassHelper(test outerInstance)
{
this.outerInstance = outerInstance;
}
public virtual void onLongPress(MotionEvent e)
{
outerInstance.hasPerformedLongPress = childView.performLongClick();
if (outerInstance.hasPerformedLongPress)
{
if (outerInstance.rippleHover)
{
startRipple(null);
}
cancelPressedEvent();
}
}
public override bool onDown(MotionEvent e)
{
outerInstance.hasPerformedLongPress = false;
return base.onDown(e);
}
}
}

What is the best way to create configurable object repository in java?

To explain more, what I want is to identify the incoming request based on some parameters in a client server arch. Suppose I receive a request on server which has some parameters like command=xyz, param1=blah, param2=blah2.
some.property.xyz=com.domain.BusinessFunction1
some.property.abc=com.domain.BusinessFunction2
Now after identifying these parameters, and looking at configurations, i should be able to call the right business function, as in above example, if I received a request in which command param is xyz, it should go through BusinessFunction1 else if it is abc it should go through BusinessFunction2. And BusinessFunction1 and BusinessFunction2 are implemented in two different Java classes.
Your best approach is to create a singleton factory, which you can populate from a database com.domain.BusinessFunction1 stored against the service name some.property.xyz. The factory will use reflection to construct the class by using Class.forName("com.domain.BusinessFunction1"); then you can call a method on this class which takes for ease of use sake a map of property names and values. Personally I'd create another factory and have specific objects for each business function. If you don't have a database you could store the name value of the business function in an XML or an enum.
Here is the idea using a Singleton and a HashMap. I would suggest you populate the factory from a database to give you more flexibility.
A generic base interface
public interface IBusinessFunction {
public void doFunction();
public void setParameters(Map<String,String> paramMap);
}
The Business functions
public class BusinessFunction1 implements IBusinessFunction {
#Override
public void doFunction() {
System.out.println(String.format("Function from business class %s called.", this.getClass().getName()));
}
#Override
public void setParameters(Map<String, String> paramMap) {
}
}
public class BusinessFunction2 implements IBusinessFunction {
#Override
public void doFunction() {
System.out.println(String.format("Function from business class %s called.", this.getClass().getName()));
}
#Override
public void setParameters(Map<String, String> paramMap) {
}
}
BusinessFactory
public class BusinessFactory {
private static BusinessFactory instance = null;
private Map<String, Class<? extends IBusinessFunction>> businessFunctionMap = null;
protected BusinessFactory() {
// Populate this from a database,
// for the ease of your example i will use a HashMap
businessFunctionMap = new HashMap<String, Class<? extends IBusinessFunction>>();
businessFunctionMap.put("some.property.xyz", BusinessFunction1.class);
businessFunctionMap.put("some.property.abc", BusinessFunction2.class);
}
public static BusinessFactory getInstance() {
if (instance == null) {
instance = new BusinessFactory();
}
return instance;
}
public IBusinessFunction getBusinessFunction(String property) {
IBusinessFunction businessFunction = null;
Class clazz = businessFunctionMap.get(property);
try {
Constructor constructor = clazz.getConstructor();
businessFunction = (IBusinessFunction) constructor.newInstance();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return businessFunction;
}
}
Test your class and factory
public class Example {
public static void main(String[] args) {
Map<String,String> parameters = new HashMap<String, String>();
parameters.put("Param1","param 1 value");
parameters.put("Param2","param 2 value");
IBusinessFunction businessFunction = BusinessFactory.getInstance().getBusinessFunction("some.property.abc");
businessFunction.setParameters(parameters);
businessFunction.doFunction();
}
}

Java - Execute a class method with a specify annotation

I have a android application, but it is not relevant.
I have a class called "Front controller" which will receive some message
through it's constructor. The message, for brievity, could be an integer.
I want somewhere else to create a new controller which will execute
a method based on the integer defined above
public class OtherController {
#MessageId("100")
public void doSomething(){
//execute this code
}
#MessageId("101")
public void doSomethingElse(){
//code
}
}
The front controller could be something like this:
public class FrontController {
private int id;
public FrontController(int id){
this.id=id;
executeProperControllerMethodBasedOnId();
}
public void executeProperControllerMethodBasedOnId(){
//code here
}
public int getId(){
return id;
}
}
So, if the Front Controller will receive the integer 100, it
will execute the method annotated with #MessageId(100). The
front controller don't know exactly the class where this method
is.
The problem which I found is that I need to register somehow
each controller class. I Spring I had #Component or #Controller
for autoloading. After each controllers are register, I need to
call the properly annotated method.
How to achieve this task? In Spring MVC, I had this system
implemented, used to match the HTTP routes. How could I implement
this in a plain java project?
Any suggestions?
Thanks to Google Reflections (hope you can integrate this in your android project.)
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections-maven</artifactId>
<version>0.9.8</version>
</dependency>
For optimisation I've added the requirement to also annotate the class with MessageType annotation and the classes should be in the same package (org.conffusion in my example):
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface MessageType {
}
The OtherController looks like:
#MessageType
public class OtherController {
#MessageId(id=101)
public void method1()
{
System.out.println("executing method1");
}
#MessageId(id=102)
public void method2()
{
System.out.println("executing method2");
}
}
The implementation will look like:
public void executeProperControllerMethodBasedOnId() {
Set<Class<?>> classes = new org.reflections.Reflections("org.conffusion")
.getTypesAnnotatedWith(MessageType.class);
System.out.println("found classes " + classes.size());
for (Class<?> c : classes) {
for (Method m : c.getMethods()) {
try {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
Object o = c.newInstance();
if (mid.id() == id)
m.invoke(o);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Maybe you can optimise and build a static hashmap containing already scanned message ids.
You need to implement some of the work by yourself using reflection, I would recommend to prepare message handlers on initial phase in regards to performance. Also you possibly want to think about Singleton/Per Request controllers. Some of the ways to implement the solution:
interface MessageProcessor {
void execute() throws Exception;
}
/* Holds single instance and method to invoke */
class SingletonProcessor implements MessageProcessor {
private final Object instance;
private final Method method;
SingletonProcessor(Object instance, Method method) {
this.instance = instance;
this.method = method;
}
public void execute() throws Exception {
method.invoke(instance);
}
}
/* Create instance and invoke the method on execute */
class PerRequestProcessor implements MessageProcessor {
private final Class clazz;
private final Method method;
PerRequestProcessor(Class clazz, Method method) {
this.clazz = clazz;
this.method = method;
}
public void execute() throws Exception {
Object instance = clazz.newInstance();
method.invoke(instance);
}
}
/* Dummy controllers */
class PerRequestController {
#MessageId(1)
public void handleMessage1(){System.out.println(this + " - Message1");}
}
class SingletonController {
#MessageId(2)
public void handleMessage2(){System.out.println(this + " - Message2");}
}
class FrontController {
private static final Map<Integer, MessageProcessor> processors = new HashMap<Integer, MessageProcessor>();
static {
try {
// register your controllers
// also you can scan for annotated controllers as suggested by Conffusion
registerPerRequestController(PerRequestController.class);
registerSingletonController(SingletonController.class);
} catch (Exception e) {
throw new ExceptionInInitializerError();
}
}
private static void registerPerRequestController(Class aClass) {
for (Method m : aClass.getMethods()) {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
processors.put(mid.value(), new PerRequestProcessor(aClass, m));
}
}
}
private static void registerSingletonController(Class aClass) throws Exception {
for (Method m : aClass.getMethods()) {
if (m.isAnnotationPresent(MessageId.class)) {
MessageId mid = m.getAnnotation(MessageId.class);
Object instance = aClass.newInstance();
processors.put(mid.value(), new SingletonProcessor(instance, m));
}
}
}
/* To process the message you just need to look up processor and execute */
public void processMessage(int id) throws Exception {
if (processors.containsKey(id)) {
processors.get(id).execute();
} else {
System.err.print("Processor not found for message " + id);
}
}
}

Unable to instantiate sub class with parameter

I keep getting the error: java.lang.NoSuchMethodException: com.production.workflow.MyWorkflow.<init>(com.production.model.entity.WorkflowEntity)
I have a constructor that is expecting WorkflowEntity so I'm not able to figure out why it's saying NoSuchMethod. Is there something about constructor inheritance that is preventing this from instantiating?
My instantiation factory:
public static Workflow factory(WorkflowEntity workflowEntity) {
try {
Class<?> clazz = Class.forName(workflowEntity.getClassName()).asSubclass(Workflow.class);
Constructor c = clazz.getConstructor(WorkflowEntity.class);
Object workflowClass = c.newInstance(clazz);
return (Workflow) workflowClass;
} catch (Exception e) {
e.printStackTrace();
logger.severe("Unable to instantiate "+workflowEntity.getClassName()+" class: " + e.getLocalizedMessage());
}
return null;
}
Workflow class:
public class MyWorkflow extends Workflow {
//no constructors
Extended class:
abstract public class Workflow {
protected static final Logger logger = Logger.getLogger(Workflow.class.getName());
private WorkflowEntity entity;
protected WorkflowProcess workflowProcess;
#Autowired
private WorkflowProcessService workflowProcessService;
/* Don't use this one */
public Workflow() { }
/* Default constructor */
public Workflow (WorkflowEntity entity) {
this.entity = entity;
//get first workflow process
//#todo this should factor in rule, for multiple starting points
for (WorkflowProcessEntity workflowProcessEntity : entity.getWorkflowProcesses()) {
workflowProcess = WorkflowProcess.factory(workflowProcessEntity);
break;
}
}
There are two problems in your code:
Constructors are not automatically inherited by subclasses. You need to add the MyWorkflow(WorkflowEntity) constructor to the MyWorkflow class.
Your new instance call needs to be made with the workflowEntity instance (and not the class instance you are giving it now)
Here:
class MyWorkflow extends Workflow {
public MyWorkflow() {
super();
}
public MyWorkflow(WorkflowEntity entity) {
super(entity);
}
}
public static Workflow factory(WorkflowEntity workflowEntity) {
try {
Class<?> clazz = Class.forName(workflowEntity.getClassName())
.asSubclass(Workflow.class);
Constructor<?> c = clazz.getConstructor(WorkflowEntity.class);
Object workflowClass = c.newInstance(workflowEntity);
return (Workflow) workflowClass;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Consider the builder pattern instead of the factory pattern. Here is an example that builds a WorkFlow that takes a WorkflowEntity constructor parameter and builds a workFlow that does not take a WorkFlowEntity pattern (just showing multiple options available via a builder).
public class WorkFlowBuilder
{
private WorkflowEntity constructorParameter;
private Class workflowClass;
public WorkFlowBuilder(Class desiredWorkflowClass)
{
if (desiredWorkflowClass != null)
{
workflowClass = desiredWorkflowClass;
}
else
{
throw new IllegalArgumentException("blah blah blah");
}
}
public void setConstructorParameter(final WorkflowEntity newValue)
{
constructorParameter = newValue;
}
public WorkFlow build()
{
Object workflowObject;
if (constructorParameter != null)
{
Constructor constructor = workflowClass.getConstructor(WorkflowEntity.class);
Object workflowObject;
workflowObject = constructor.newInstance(workflowEntity);
}
else
{
workflowObject = workflowClass.newInstance();
}
return (WorkFlow)workflowObject;
}
}
Use this as follows:
WorkFlowBuilder builder = new WorkFlowBuilder(MyWorkFlow.class);
WorkflowEntity entity = new WorkFlowEntity();
WorkFlow item;
entity... set stuff.
builder.setConstructerParameter(entity)
item = builder.build();
I think you just want to pass in the workflowEntity into the constructor on the newInstance call, instead of the typed Class.
Constructors lost their outside visibility during inheritance.
You need to redefine it in MyWorkflow.
This is done so because sub classes may not support the super class creation process. So super object constructors does not make sense to sub classes and it's even unsafe if they were visible outside.
You should also remove the default constructor if your class can be used if instantiated without WorkflowEntity. Just remove it from Workflow and do not add to MyWorkflow.
UPD
You should also consider using generics to avoid class casting.
public Workflow create(WorkflowEntity workflowEntity) throws
ClassNotFoundException, NoSuchMethodException, SecurityException
, InstantiationException, IllegalAccessException
, IllegalArgumentException, InvocationTargetException {
Class<? extends Workflow> clazz = Class.forName(workflowEntity.getClassName()).asSubclass(Workflow.class);
Constructor<? extends Workflow> c = clazz.getConstructor(WorkflowEntity.class);
Workflow workflowClass = c.newInstance(clazz);
return workflowClass;
}
class WorkflowEntity {
public String getClassName() {
return "className";
};
}
class Workflow {
Workflow(WorkflowEntity entity) {
};
}
class MyWorkflow extends Workflow {
MyWorkflow(WorkflowEntity entity) {
super(entity);
}
}

Categories