I am creating a game where characters can have modules attached to them which provide extra functionality, for example there could be a 'banker' module which listens for a click event and opens a menu for banking. Modules are user creatable by extending the Module class and registering an instance with a ModuleFactory. Modules are able to serialize themselves and load themselves from a serialized form (saving to XML) when is passed in the constructor.
The problem I am having is that when loading the modules I have the name and an instance of every module but I cannot make a new instance of each module.
Is it acceptable to make a newInstance() method inside of each module which returns an instance of the module?
I know it is possible to use reflection for this but most of the time I find reflection to be more trouble than the benefits I get from it.
It is possible to do something like this, since you said you already know the names of each Module (hopefully in some sort of list).
Class<?> temp = Class.forName("ModuleName");
Object obj = temp.newInstance();
This is actually reflection.
Originally I had this, but my above code is superior, because this will require you to have a method that creates a new instances inside each Module. It works, but it is messy. Think of it as this, an object that creates a clone of itself, that is just weird.
public static Module createInstance()
{
return new ThisModule();
}
If you want a new instance as a copy of the existing instance, you can use the clone method,
Otherwise create a factory method which creates instances for you,
public static Module createInstance(){
return new Module();
}
I m not sure if I completely understood what you want
Create a static method in each module to instantiate. This is static factory method. Effective java book says it is indeed good practice to create objects through static factory methods.
I think we can call static methods on objects( though not a good practice).
If i understand you right, you want to extend the behavior of an object and be able to send/serialize it via XML to a client and back (frontend <-> backend communication).
I think what you are looking for is something like a decoration for your Modules and Submodules. Maybe you should build them decoratable to each other, like an InputStream.
something like this:
MyBaseModule base = new MyBaseModule();
BankerModule banker = new BankerModule(base);
ExtendedBankerModuler extBanker = new ExtendedBankerModule(banker);
Maybe call extBanker.toXML() to get the XML to send it to the frontend.
You can wrap each module with the tags of the decorations ones...
<serialized>
<module>
<type>ExtendedBankerModule</type>
<description>extended banker module</description>
<decorates>
<module>
<type>BankerModule</type>
<description>banker module</description>
<decorates>
<module>
<type>MyBaseModule</type>
<description>basic module</description>
<decorates></decorates>
</module>
</decorates>
</module>
<decorates>
</module>
</serialized>
Related
I have a library class, that is, a class that I load from a JAR, the source code is outside of my control. We instanciate it in our project in several places, and a property of the created objects should be always set. Unfortunately there is no central settings for the library, so I have created a subclass:
public class MyClass extends LibraryClass {
public MyClass() {
super();
super.setSomeProperty();
}
}
and then I replaced all instanciation of LibraryClass with MyClass. It works fine, but I want to prevent myself and my collegues to instanciate a LibraryClass in the future.
Is it possible to mark the LibraryClass (or its constructor) as deprecated by Maven or by Eclipse or somehow else? It would be a compile time solution.
Or is it possible to use some Spring/Aop magic to replace all instancieated LibraryClass with MyClass in runtime?
Since you mention to mark the constructor as deprecated (which would not actually forbid it) - if you are using something like sonar, you could create an own rule which marks the usage as error, exept for your subclass.
If you are using Spring in your application and all bean instantiation is done through Spring, on application startup check if a bean exist of type LibraryClass. Throw an exception if it exists. Similar solution can be implemented for any other framework used for bean instantiation.
We extend JAXBEqualsStrategy via pom:
<xjcArg>-Xequals-equalsStrategyClass=com.acme.foo.CustomEqualsStrategy</xjcArg>
The CustomEqualsStrategy extends JAXBEqualsStrategy. After running MAVEN clean install generate-source in Eclipse (Keplar) our model classes have equals method like this:
public boolean equals(Object object) {
final EqualsStrategy strategy = new CustomEqualsStrategy();
return equals(null, null, object, strategy);
}
Whereas if we do not extend JAXBEqualsStrategy, our model classes have equals method like this:
public boolean equals(Object object) {
final EqualsStrategy strategy = JAXBEqualsStrategy.INSTANCE;
return equals(null, null, object, strategy);
}
JAXBEqualsStrategy has
public static EqualsStrategy INSTANCE = new JAXBEqualsStrategy();
We expected to get
final EqualsStrategy strategy = CustomEqualsStrategy.INSTANCE;
in the generated equals method and are struggling to accomplish it.
You do not want to use CustomEqualsStrategy.INSTANCE. Using new CustomEqualsStrategy() is correct and should be preferred unless you have very good reasons for doing otherwise.
Since CustomEqualsStrategy extends JAXBEqualsStrategy, that means that unless you define your own INSTANCE field inside CustomEqualsStrategy, CustomEqualsStrategy.INSTANCE is the same as JAXBEqualsStrategy.INSTANCE, which means that you would be using an instance of JAXBEqualsStrategy after all.
Plus, using an INSTANCE field like that effectively signals that your class is meant to be used as a singleton, and thus has to be stateless. Most classes are not stateless, and even for classes that are, many such classes don't need to be used in a singleton style.
In short, really just stick with new CustomEqualsStrategy(). The code will have fewer surprises and you'll be happier for it. (Also, from reading the code for JAXBEqualsStrategy, perhaps you should be extending DefaultEqualsStrategy instead.)
Disclaimer: Plugin author here.
Actually, you can also get .INSTANCE or .getInstance()-calls generated as well. Please see this code:
https://svn.java.net/svn/jaxb2-commons~svn/basics/trunk/basic/src/main/java/org/jvnet/jaxb2_commons/plugin/util/StrategyClassUtils.java
So:
If the class of your equals strategy is known to the plugin in the runtime AND
Your class has a public static getInstance() method of the correct type OR
Your class has a public static field INSTANCE of the correct type
Then the plugin will use YourStrategy.getInstance() or YourStrategy.INSTANCE instead of new YourStrategy().
I guess you already have an INSTANCE method. Please try to include the JAR with your strategy into the XJC classpath (so that plugin could resolve your strategy class during the compile time).
Please also feel free to file an issue to support syntax like -Xequals-equalsStrategyInstanceField=com.acme.foo.CustomEqualsStrategy.INSTANCE or InstanceMethod accordingly.
i'm just learning java, and i meet some problems.
Here we have simple factory pattern:
public class SomeFactory {
...
public static void registerProduct(String name, Class<? extends IProduct > f)
}
public SomeProduct implements IProduct {
static {
SomeFactory.register("some product", SomeProduct.class);
}
...
}
All products should register themselves at factory.
But before using this code, all Products classes should be loaded.
I can put Class.forName() somewhere, for example in main function.
But i want to avoid such sort of manual classes loading. I want just add new IProduct
implementations, without updating other parts(such as SomeFactory or Main methods, etc.).
But i wonder, is it possible to automatically load some classes(marked with annotation, for example)?
P.S I want to notice, that no other classes will be added at run-time, all IProduct implementations are known before compiling.
UPD#1
Thank for your answering!
But is it possible to make auto-generated property-file with IProduct instances?
I mean is it possible to make some build-time script(for maven for example) that generates property-file or loader code? Are there such solutions or frameworks?
UPD#2
I finished with using Reflections library that provides run-time information, by scanning classpath at startup.
This is possible, but not easily. It would need to scan all the classes in the classpath to see if they have an annotation or implement the IProduct interface. See How do you find all subclasses of a given class in Java? for answers to such a problem.
I would do keep it simple and just have a list of classes to load, either in the factory itself, or in an external file (properties file, for example).
Have each product register itself, using a static block like this:
class MyProduct1{
static{
SomeFactory.register(MyProduct1.getClass());
}
..
..
}
An external property file can keep track of all Products.
Your main method can parse this list of Products and do a Class.forName("..").
This way you wouldnt need to code any specific product, just the property file keeps changing. Ah! yes adding security registration would also be a plus point.
Note: I'm just proposing an idea, I'vent tried it myself :)
I have three Modules in Guice:
ReflectionsModule, for providing Metadata (via Reflections)
PersistenceModule, for Data Access Objects and Others
WebModule, for Web Stuff
Simply put, both PersistenceModule and WebModule will fetch a object which is made from Reflections Module. I can not find a very friendly way to do this in guice.
I think PrivateModules will be a suitable way around, but I am not sure how to implement that. Any ideas?
Thank you.
Some additional details
I am using Reflections. It is basically a wrapper to load persistence metadata from a static resource. So basically supposed a parsed XML file into a JavaBean. Thats the concern of the ReflectionsModule.
From this metadata into the javabean, I need to setup the persistence (its a Google App Engine App, using Objectify) and load additional classes and bind them while reading some annotations within. I do not want to load the resource, so I'd like to refer to the resource loaded from the first example.
For now, the ReflectionsModule also binds the two subsequent modules, which I get (correctly) and apply them to the createChildInjector which came when building with just the first module. As os now, it works. I just would like to know which way would be the best one.
Simply speaking, PrivateModules expose only bindings that are explicitly exposed using #Exposed annotation of the .expose() method. Therefore, if PersistenceModule and WebModule are both PrivateModules, you can do the following:
public class WebModule extends PrivateModule {
#Override
public void configure() {
install(new ReflectionsModule());
// do stuff...
expose(SomeClassFromWebModule.class);
}
}
public class PersistenceModule extends PrivateModule {
#Override
public void configure() {
install(new ReflectionsModule());
// do stuff...
expose(SomeClassFromPersitenceModule.class);
}
}
In this way, the bindings from ReflectionsModule will not be exposed further than the two PrivateModules and will therefore not run into each other.
It is generally a good practice to only expose classes that can only be provided by one Module.
EDIT: better answer found: https://stackoverflow.com/a/5504903/105741 - basically use #Provides annotation to get method parameters in your module injected with your dependencies from other modules. Works much nicer. I.e. for the binding that requires the DependencyClass, I move that code into a method, expose it with the #Provides annotation, and add the DependencyClass as a method parameter.
#dyross - I don't think that's what he's asking.
It's not a good idea to create the ReflectionModule more than once, and PrivateModules don't have anything to do with the problem - that of sharing bindings to children modules (if I understand him correctly). I have the same need, and have used the technique of passing in the required object to the children modules ie.
Injector parentInjector = Guice.createInjector(new ParentModule());
DependencyClass dep = parentInjector.getInstance(DependencyClass);
injector = parentInjector.createChildInjector(new ChildModule(dep));
i.e.
Injector reflectionsModule = Guice.createInjector(new ReflectionsModule());
DependencyClass dep = parentInjector.getInstance(DependencyClass);
injector = parentInjector.createChildInjector(
new PersistenceModule(dep),
new WebModule(dep));
Not ideal, but serves the purpose.
It also just occured to me that you could pass in the injector to the child modules too, and getInstance() from directly inside the child modules.
In my current project I have 2 modules ModuleA and ModuleB, and inside ModuleA and ModuleB I have a class called 'Student' (same class name, same attributes, but for some purpose ModuleA must call ModuleB to do the actual task). They communicate to each other through Web Services. Now I want ModuleA web service to call ModuleB proxy to do the actual task.
In my ModuleA web service I have a method to create a record:
public void createStudent(ModuleA.Student student){
// Here will call ModuleB proxy to do the actual task which is create.
*moduleBFacade().createStudent( );*
}
In my ModuleB Proxy:
public void createStudent(ModuleB.Student student){}
So now the problem is, I cannot pass the moduleA object into the createStudent method as it only takes moduleB objects as arguments.
Any idea how to deal this problem? Please give me some suggestions.
As you are invoking with WS can you convert the moduleA.Student to xml and then change the namespace of the xml and then instantiate a moduleB.Student object from xml.
Something like:
String xmlA = moduleA.Student.toXml();
//Change namespace. Also, Compare the genrated xml of ModuleA and ModuleB.
ModuleB.BStudent studentB= StudentDocument.Factory.parse(xmlA, ..);//second argument can be diff namespace
*moduleBFacade().createStudent(studentB);
You cannot change the class of an object in Java. Also, you cannot "merge" two classes into one class. What you could do is to introduce a common interface, but for that you must own the sourcecode of both classes.
Given the constraint that you can change neither of the two classes, then manually converting ModuleA.Student to ModuleB.Student and back is the best option you get.
PS: as an alternative you can use reflection. Given that both classes have the same attribut names, then mapping from one class to the other should not be a problem.
public static <A,B> B convert(A instance, Class<B> targetClass) throws Exception {
B target = (B) targetClass.newInstance();
for (Field targetField: targetClass.getFields()) {
Field field = instance.getClass().getField(targetField.getName());
targetField.set(target, field.get(instance));
}
return target;
}
Usage:
StudentB studentB = convert(studentA, StudentB.class);
The example above assumed that all fields are private. If they are not, then the same can be can done with methods (module mapping setter names to getter names).
Circular dependency == bad design.
Redesign the modules to remove the circular dependency.
Might not sound right, but here:
Java code
supposing student object passed is of type ModuleAStudent
//create a new bStudent with main criteria
ModuleBStudent bStudent = new ModuleBStudent();
bStudent.setStudentId(student.getStudentId());
bStudent.setStudentNo(student.getStudentNo());
//finally
moduleBFacade().createStudent(bStudent);
UPDATE
Since your object is the same in the two packages and you are making a web service, i would suggest this Simple framework, yea its called Simple actually. Simple helps you serialize your object to XML and deserialize it back, pretty Simple.
You can use BeanUtils.copyProperties to copy to similar beans (note, this is a shallow copy)