I'm using generics to get my code reusable and to utilize dependency injection.
I have two Interfaces: DataParserImplementation and ObjectImplementation. I have classes that implement each: SalesRepbyId implements DataParserImpl (it parses the data into objects and puts those objects into collections). SalesRep implements Objectimpl (It is the object for a specific dataset).
I'm trying to get it so that I can select which kind of Objectimpl I use in my SalesRepbyId class so I can remove the coupling.
I know there is something called reflection that I've been told is the method I need to use. I also have heard about a "Factory Pattern" and a "Properties file" that allows me to do what I want to do. A lot of this is very confusing so please explain it like I'm five.
Here is the code with where it stops working:
EDIT: Revisions based on comments: I want to specify the type of DataObject (D) my class uses by passing it through the constructor via a common interface and using generic types. When I try and use it instead of a concrete implementing class, I get the error. I can't find anything about this error.
public class SalesRepbyId<D extends ObjectImplementation> implements DataParserImplementation<Map<String,D>> {
private FileParserImplementation<ArrayList<String[]>> FileParser;
private D dataObject;
public SalesRepbyId(FileParserImplementation<ArrayList<String[]>> FileParser,D d){
this.FileParser = FileParser;
this.dataObject = d;
}
#Override
public Map<String, D> Parse() {
try{
//reads the file and returns an array of string arrays
ArrayList<String[]> Salesrep_contactlist = FileParser.ReadFile;
//here it still says "Unknown Class." that's the problem
Map<String, dataObject> SalesrepByIdMap = new HashMap<>();
//I want to be able to put in any class that implements
//dataObject into this class and have it run the same way.
Summary of what I did
I Implemented the Factory Design pattern and created a properties file which allowed me to reflect in the class I wanted instead of trying to use a generic DataObject (or D) type.
Details of Solution
Reflecting the class using the properties file "config.properties" and then casting it to type Objectimplementation allowed me to use any class that implemented that interface (and was implemented in the Factory and set in the properties file). I then refactored all instances of D to type ObjectImplementation since the parent interface is the layer of abstraction needed here rather than a generic concrete class.
Why it didn't work the way I tried it in the question
the reason the generic D type doesn't work with reflection is because reflection uses a concrete classtype determined at runtime and the generic D type is specified before runtime. Thus I was trying to reflect in the classtype and its methods/instances without properly using reflection and the code was telling me that the classtype was unknown at the time I needed it.
Code example to compare to the Question code
Example of the working code:
public class SalesRepbyId implements
DataParserImplementation<Map<String,ObjectImplementation>> {
private FileParserImplementation<ArrayList<String[]>> FileParser;
//the Factory class that creates instances of the reflected class I wanted
private ObjectFactory Factory = new ObjectFactory();
public Map<String, ObjectImplementation> Parse() {
//the proeprties object which then loads properties from a file and reflects the classtype I want
Properties prop = new Properties();
//loading in the classtype and casting it to the subclass of ObjectImplementation that it actually is
prop.load(SalesRepbyId.class.getResourceAsStream("config.properties"));
Class<? extends ObjectImplementation> Classtouse = Class.forName(prop.getProperty("ObjectImplementation")).asSubclass(ObjectImplementation.class);
//construct instances of 'Classtouse' and parse the data into these dynamically typed objects
//return the map that holds these objects
}
Related
Let's say I have a generated Entity like this:
public class QCandidate extends EntityPathBase<Candidate> {
public final com.avisto.candisearch.persistance.model.enums.QAvailabilityEnum availability;
public final DatePath<java.util.Date> birthDate = createDate("birthDate", java.util.Date.class);
public final NumberPath<Long> cvId= createNumber("cvId", Long.class);
public final StringPath city = createString("city");
}
My input values are the fields names ("availability","birthDate","cvId"...) and a string value that I should use to perform a 'like' with all the fields.
I want to build a query starting from the field names that:
casts Dates and Numbers to strings and lowercases them
if the field is an EntityPathBase (like availability) extracts the id and then again casts to lowercased string
Something like:
lower(cast(C.cvId as varchar(255))) like 'value'
for each field.
I can do this usign querydsl-sql module, but I want to achieve it using only the jpa module.
I'm not interested in the mechanism of creating the FULL 'where' clause (I know I have to use the BooleanBuilder, or at least, this is what I do in the sql version).
What I want to know is how to create the individual 'where' conditions basing on the field type.
I'm trying to use a PathBuilder but it seems that to use methods like "getString or getBoolean" you already have to know the type of the field that you are trying to extract. In my case, since I start just from the field name, I can't use these methods and I don't know how to identify the type of each field starting from the field name, so I'm stuck.
May be a bit ugly, but workable suggestion.
Note, that the number of field types that PathBuilder accepts is quite limited.
You definitely can find the field class from field name (using reflection or by maintaining a member map updated with each field).
Just implement handling for each specific type.
This can be ugly bunch of if..else or, for more elegant solution, create Map of type handlers [class->handler], each handler implements interface method to handle specific type.
Pseudocode:
//building query
for each field
Class fieldClass = findFieldClas(.., field) //use reflection or map
PathHandler handler = handlers.get(fieldClass)
handler.process( ...)
//type handler interface
public interface Handler{
public xx process(? extends DataPathBase);
}
//specific type handler implementation
public class BooleanHandler implements Handler{
public xx process(? extends DataPathBase path){
BooleanPath bPath = (BooleanPath)path;
...
}
//intitialize handlers map singleton or a factory in advance
handlers.put(BooleanPath.class, new BooleanHandler());
...
Note this is a generic solution if you have many classes. If you have only one specific class, you can just create a permanent map of fieldName->Handler and avoid lookup for the field class.
Again, this is by no means a pretty solution, but should work.
I am using jackson to handle JSON (de)-serialization. I have a bunch of classes which are annotated with are essentially objects holding properties and associated getters and setters.
However, I often find that at some point I want to add additional properties which I don't want to include in the (de)-serialization process. This does work using #JsonIgnore, but it strikes me as relatively ugly since I have to add the annotation everywhere and things break down as soon as I forget.
I would like to know if there is a better way to separate the ignored and serialized properties. I have the following two ideas:
Use inheritance, add the new properties to the inherited class:
// everything here should be (de)-serialized
class Base {
public int getJSONProperty() {...}
}
// nothing specific to the class Derived should be (de)-serialized
class Derived extends Base {
// *not* to be included
public SomeClass getAdditionalProperty() {...}
}
However, I don't know how to tell jackson to deserialize the Derived
objects as Bases. Is this possible (Does jackson make guarantees
regarding (non)-polymorphic serialization of classes)?
Use MixIn annotations. This would require an additional abstract
class for each existing class. Also I am not sure whether this solves
the problem. Are getters which do not appear in the MixIn base class
ignored automatically or do I need to #JsonIgnore them manually?
I've seen that you don't like the previous solution i've provided, so I'm again here to provide another way to do what you want using Gson Library. I hope to help you this time.
This is The Base Class that you want to serialize
public class Base {
public int getJSONProperty() {
return jsonProperty;
}
private int jsonProperty = 2;
}
This is The Derived Class that you don't want to serialize
public class Derived extends Base{
public String getAdditionalProperty(){
return additionalProperty;
}
private String additionalProperty = "value-not-to-serialize";
}
Using Type type = new TypeToken<Base>(){}.getType(); you can define the class to use for serialization so you get the JSON String using:
Derived derived = new Derived();
Gson gson = new Gson();
Type type = new TypeToken<Base>(){}.getType();
String jsonString = gson.toJson(derived, type);
You know Gson? it's a good library to handle JSON.
You can use transient keyword to define variable thats not must be serialized, this works with Gson (It should work well with jackson, but i'm not sure)...
class Base {
// (de)-serialized
private int jsonProperty;
// not (de)-serialized
private transient SomeClass additionalProperty;
}
I think the best approach is to add annotation or use the transient variable.
Create the inheritance only for the purpose of serialization an object complicates the application uselessly in my point of view...
I'm trying to persist some enums in Hibernate and it looks like my two options for built in support are to use the name of the enum, which I would rather not do because it's string based instead of int based, or the ordinal of the enum, which I would rather not do because if I add one of the enum values at the top of the class later on, I break everything down the line.
Instead, I have an interface called Identifiable that has public int getId() as part of its contract. This way, the enums I want to persist can implement Identifable and I can know that they'll define their own id.
But when I try to extend EnumValueMapperSupport so I can utilize this functionality, I'm greeted with errors from the compiler because the EnumValueMapper interface and the EnumValueMapperSupport class are not static, and thus are expected to be locked into a given EnumType object.
How can I extend this functionality in Hibernate, short of rewriting a bunch of Hibernate code and submitting a patch. If I can't, is there another way to somehow store an enum based on something other than the ordinal or name, but instead on your own code?
In a related thought, has anyone personally been down this road and decided "let's see how bad the name mapping is" and just went with name mapping because it wasn't that much worse performance? Like, is it possible I'm prematurely optimizing here?
I'm working against Hibernate version 5.0.2-final.
At least for Hibernate 4.3.5 the EnumValueMapper is static - although private.
But you can extend EnumValueMapperSupport in an extension of EnumType:
public class ExampleEnumType extends EnumType {
public class ExampleMapper extends EnumValueMapperSupport {
...
}
}
To create an instance of this mapper you need an instance of your EnumType:
ExampleEnumType type = new ExampleEnumType();
ExampleMapper mapper = type.new ExampleMapper();
Or you create it inside your type:
public class ExampleEnumType extends EnumType {
public class ExampleMapper extends EnumValueMapperSupport {
...
}
public ExampleMapper createMapper() {
return new ExampleMapper();
}
}
I have 2 class just call it "Stuff" and "Customer", the classes based on my database table (JDBC) and have abstract class because this 2 classes has same few property(Id,Name), my abstract class containing(Id,Name, along with setter and getter from Id and Name variable).
I was creating 2 more class ("ExecuteStuff" and "ExecuteCustomer") which has a goal to execute a query for manipulate a data in my database,because this situation "ExecuteStuff and ExecuteCustomer" class should have method insert, update,delete and show for manipulate and showing a data from my database, because "ExecuteStuff" and "ExecuteCustomer" need a same method for process a data from my database , I decided to creating my own interface called "myData" which is contain 4 mehod (insertData(), updateData(),deleteData() and showData()) for class "ExecuteStuff" and class "ExecuteCustomer".
My problem is, what type data should I use for parameter inside a method in my interface "myData", for example = public int insertData(Stuff stuff); this method will work for "ExecuteStuff" but not for "ExecuteCustomer" because "ExecuteStuff" and "ExecuteCustomer" has a different object type.
Or a graceful way to solve this problem.
If I understand you correctly, you can use a generic type in your interface. That way it won't matter what the data type of the parameter you pass in is.
Here is a link that explains generics:
https://docs.oracle.com/javase/tutorial/java/generics/types.html
Another solution is to use:
public int insertData(Object obj);
Since both Stuff and Customer are objects.
Hope I was able to help!
You could use a generic parameter:
interface MyData {
public <T> T insertData(T data);
}
Class example:
class MyCustomClassThat implements MyData{
#Override
public <T> T insertData(T data) {
return data;
}
}
This makes the insertData method accept any class. Then you can operate on it however you like. Finally, we return the object originally presented; just in case you operated on the data object itself.
I want to provide an annotation as the following:
public #interface CloneField
{
String sourceField();
Class<?> customCloner();
}
Where people can annotation fields on their classes and some framework will automatically copy fields to their classes instances by running a method from the customCloner on an external data source object.
For example:
class Test {
#CloneField(sourceField = "demoTest", customCloner = StringToIntCloner.class)
private int testField;
This will copy a string value from a field named demoTest on the external data source object into an int field on the user's object.
Since the customCloner doesn't hold any data I would want to define the cloning method as static without the need to instantiate it just for calling a method.
Usually I would define the custom cloner class as:
Class <? extends FieldCloner> customCloner;
where FieldCloner has a method for cloning.
But since static methods are not supported on interfaces there isn't a clean way to do so.
Is there an elegant way to do so in Java 7?
Beside the problem of running the method which can be solved by reflection I want to verify at compile time that the customCloner class has the appropriate method for cloning.