java generic cast question - java

I want to implement a sort of transfer object pattern. So, i have a method that fills object´s properties via BeanUtils.copyProperties(..,..) (apache common).
Here is the code:
public abstract class BaseTO<TObject> {
public Long id;
/***
* Obtains id of the object that´s transfered
* #return object´s id
*/
public Long getId() {
return id;
}
/****
* set transfered object´s id
* #param id object´s id
*/
public void setId(Long id) {
this.id = id;
}
/***
* Fill transfer object properties.
* #param entity entity to be transfered
* #return self reference
*/
public BaseTO<TObject> build(TObject entity){
try {
BeanUtils.copyProperties(this, entity);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
customDataTransformation(entity);
return this;
}
protected void customDataTransformation(TObject entity) {
}
}
CustomerTO Class
public class CustomerTO extends BaseTO<Customer> {
private String name;
private String surname;
private String email;
private String sex;
private DocumentType documentType;
private String documentNumber;
--- getters and setters
#Override
protected void customDataTransformation(Customer entity) {
this.sex = Sex.MALE.equals(entity.getSex()) ? "M" : "F";
}
}
the problem
CustomerTO toEdit = (CustomerTO) (customerId!=null ? new CustomerTO().build(entityObject):new CustomerTO());
as you can see here have to cast to (CustomerTO). I want if it´s possible avoid that, to make the code simpler.
Is it posible that public BaseTO build(TObject entity) can return the object of the subclass??
I hope to be clear.
Thanks in advance.

Maybe try this:
class BaseTO<TObject, R extends BaseTO<TObject,R>> {
public R build(TObject entity) {
and then CustomerTO:
class CustomerTO extends BaseTO<Customer, CustomerTO> {
or less restrictively, only change the build signature:
public <X extends BaseTO<TObject>> X build(TObject entity) {
But IMHO better approach will be simply adding constructor to TO with TObject parameter.
public BaseTO(TObject entity) {
try {
BeanUtils.copyProperties(this, entity);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
customDataTransformation(entity);
}
then in each extending class create simple constructor
public CustomerTO(Customer entity) {
super(entity);
}
and forget about the build method and use it simply
CustomerTO toEdit = (customerId!=null ? new CustomerTO(entityObject):new CustomerTO());

This compiles:
public class BaseTO<T> {
public BaseTO<T> build(T entity) {
return this;
}
public static class CustomerTO extends BaseTO<String> {
#Override public CustomerTO build(String string) {
return (CustomerTO) super.build(string);
}
}
but you will have to override build for all subclasses of BaseTO. You write explicitly the cast only once instead of every time you call build.
EDIT: see the point raised by #Paul in the comments above. You might be suffering from "give a man a hammer and everything looks like a nail to him."

Related

Generic Interface in different classes

In my project, I have to use the database pretty often and I decided to create an interface and then implement it in different classes since they will all use the same methods.
public interface Project<E> {
void createTable();
void insert(E obj);
E select(int id);
void delete(int id);
void update(E obj, int id);
}
I try to implement it in one of my classes like below:
public class Person implements Project {
//createTable method
//select method
//delete method
public void insert(Person p) {
Connection connection = null;
PreparedStatement ppStm = null;
try {
connection = ConnectionConfiguration.getConnection();
ppStm = connection.prepareStatement("INSERT INTO person (first_name, last_name)"
+ "VALUES (?,?,?)");
ppStm.setString(1, p.getName());
ppStm.setString(2, p.getLname());
ppStm.executeUpdate();
} catch(Exception e) {
e.printStackTrace();
} finally {
if (ppStm != null){
try {
ppStm.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//update method similar to insert();
}
The problem is that when I try to override the insert() and update() methods it shows me an error message "the method must override or implement a supertype method". I used generics since I thought it would work in my code seeing as I have different classes of different objects to implement it to but I am not understanding the right implementation I guess. I would like to know how I can change my interface or its implementation in my classes so it can work. Also when I remove the #Override it removes the error but still shows that I am not implementing all the methods.
Thank you in advance.
You can use DAO pattern
public interface DAO<T> {
void createTable();
void insert(T t);
T select(int id);
void delete(int id);
void update(T t, int id);
}
Implementation
class PersonDAO implements DAO<Person> {
#Override
public void createTable() {}
#Override
public void insert(Person person) {
/// Connection connection = null;
/// PreparedStatement ppStm = null;
// Detailed implementation
//// .............
}
#Override
public Person select(int id) {
return null;
}
#Override
public void delete(int id) {}
#Override
public void update(Person person, int id) {}
}

AspectJ - Use reflection to instanciate object of not public class

I am trying to instanciate an object of a non public class in AspectJ.
I have this class:
package ca1.business;
public class Bill {
int id;
String idOperator;
String idClient;
Bill(int id, String idOperator, String idClient) { /* (...) */ }
public String toString() { /* (...) */ }
public boolean equals(Object o) { /* (...) */ }
public int getId() { /* (...) */ }
public String getOperator() { /* (...) */ }
public String getClient() { /* (...) */ }
}
In the aspects class I wanted to be able to do:
Bill b = new Bill(currInvoice, idOperator, idClient);
The problem is that I get an error:
The constructor Bill(int, String, String) is not visible
So I investigated and tried to use reflection like it's explained in this post.
try {
Constructor<Bill> cons = Bill.class.getDeclaredConstructor(null);
cons.setAccessible(true);
Bill invoice = cons.newInstance(null);
invoice.id = 1;
invoice.idOperator = "foo";
invoice.idClient = "bar";
// etc...
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
But I get an error in the lines:
invoice.id = 1;
invoice.idOperator = "foo";
invoice.idClient = "bar";
The error is:
The field Bill.X is not visible.
Does anyone know if there is any workaround?
Why use reflection?
Let us assume the Bill class looks like this:
package ca1.business;
public class Bill {
int id;
String idOperator;
String idClient;
Bill(int id, String idOperator, String idClient) {
this.id = id;
this.idOperator = idOperator;
this.idClient = idClient;
}
#Override
public String toString() {
return "Bill [id=" + id + ", idOperator=" + idOperator + ", idClient=" + idClient + "]";
}
public static Bill instance;
public static void main(String[] args) {
System.out.println(instance);
}
}
We want our aspect to populate the static member before main is executed (silly example, just for demo):
Option A: privileged aspect
package de.scrum_master.aspect;
import ca1.business.Bill;
public privileged aspect MyAspect {
before() : execution(public static void main(String[])) {
Bill.instance = new Bill(11, "operator", "client");
}
}
Option B: put aspect into package ca1.business
The constructor is package-private, i.e. other classes in the same package can access it.
package ca1.business;
public aspect MyAspect {
before() : execution(public static void main(String[])) {
Bill.instance = new Bill(11, "operator", "client");
}
}
Option C: put factory class into protected package as a helper
package ca1.business;
public class BillFactory {
public static Bill create(int id, String idOperator, String idClient) {
return new Bill(id, idOperator, idClient);
}
}
package de.scrum_master.aspect;
import ca1.business.Bill;
import ca1.business.BillFactory;;
public aspect MyAspect {
before() : execution(public static void main(String[])) {
Bill.instance = BillFactory.create(11, "operator", "client");
}
}
Console log for each option A, B, C
Bill [id=11, idOperator=operator, idClient=client]

How to change the POJO property name when returning JAX-RS Response?

I want to use the default JAX-RS response deserializer.
Here is my POJO
#JsonIgnoreProperties(ignoreUnknown = true)
public class Email
{
private String mFrom;
private List<String> mTo;
private List<String> mCc;
private List<String> mBcc;
private String mSubject;
private String mText;
public void setFrom(String from)
{
mFrom = from;
}
#JsonProperty("from")
public String getFrom()
{
return mFrom;
}
#JsonProperty("to")
public List<String> getTo()
{
return mTo;
}
public void setTo(List<String> to)
{
mTo = to;
}
#JsonProperty("carbon_copy")
public List<String> getCc()
{
return mCc;
}
public void setCc(List<String> cc)
{
mCc = cc;
}
#JsonProperty("blind_carbon_copy")
public List<String> getBcc()
{
return mBcc;
}
public void setBcc(List<String> bcc)
{
mBcc = bcc;
}
}
This my JAX-RS code.
#GET
#Produces("application/json", "application/xml", "text/xml")
public Response getEmails() {
List<Email> emails = getEmails(); //returns list of emails
return Response.ok(emails).build();
}
output
[{"from":"example#isp.com","to":[ ],"cC":[ ],"bCc":[ ],"subject":"my subject","text":"email from admin"}]
I want to change "cC" to the "carbon_copy". I want to solve this using the JAX-RS Response. How do I get JAX-RS to use the jackson annotated property name. Do I need to override something?
My current implementation i did the following.
public class JsonDeserializer
{
private static ObjectMapper mMapper;
static
{
mMapper = new ObjectMapper();
mMapper.setSerializationInclusion(Inclusion.NON_NULL);
}
#SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> T fromInputStream(InputStream is, Class t)
{
try
{
return (T) mMapper.readValue(is, t);
}
catch (JsonParseException e)
{
e.printStackTrace();
}
catch (JsonMappingException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (ClassCastException e)
{
e.printStackTrace();
}
return null;
}
}
Response.ok(JsonDeserializer.toJson(emails)).build();
Is there away to do it without creating another class to handle the deserialization process.
Mix-in can help you resolve this. You need to create an abstract class say "EmailExpanded" that has the property something like this:
#JsonProperty("carbon_copy")
public abstract List<String> getCc();
Then add that mixin:
emailExpandMapper = new ObjectMapper();
emailExpandMapper.getSerializationConfig().addMixInAnnotations(
Email.class, EmailExpanded.class);
emailExpandMapper.getSerializationConfig().setSerializationInclusion(
Inclusion.NON_NULL);
Later in the code while you send the response:
emailExpandMapper.writeValueAsString(emails)
You can read more about Mixins in the web.

Java cloning abstract objects

I'm wondering if there is any way to do the following. I have an abstract class, Shape, and all its different subclasses and I want to override the clone method. All I want to do in the method is create a new Shape from the toString() of the current one. Obviously I can't do the following because Shape is abstract. Is there another way to do this because overriding clone in every subclass just for a simple name change seems useless.
public abstract class Shape {
public Shape(String str) {
// Create object from string representation
}
public Shape clone() {
// Need new way to do this
return new Shape(this.toString());
}
public String toString() {
// Correctly overriden toString()
}
}
You can try to use reflection:
public abstract class AClonable implements Cloneable{
private String val;
public AClonable(){
}
public AClonable(String s){
val=s;
}
public String toString(){
return val;
}
#Override
public AClonable clone(){
try {
System.out.println(getClass().getCanonicalName());
AClonable b= getClass().getDeclaredConstructor(String.class).newInstance(val);
return b;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
in the clone() method you call getClass(). Because the ACloneble ist abstract, there call will allways go to the concrete class.
public class ClonebaleOne extends AClonable{
public ClonebaleOne(){
super();
}
public ClonebaleOne(String s) {
super(s);
// TODO Auto-generated constructor stub
}
}
and
public class ClonebaleTwo extends AClonable{
public ClonebaleTwo(){
super();
}
public ClonebaleTwo(String s) {
super(s);
// TODO Auto-generated constructor stub
}
}
and finally
public static void main(String[] args){
AClonable one = new ClonebaleOne("One");
AClonable tow= new ClonebaleTwo("Two");
AClonable clone = one.clone();
System.out.println(clone.toString());
clone = tow.clone();
System.out.println(clone.toString());
}
Output:
ClonebaleOne
One
ClonebaleTwo
Two
But it's more a hack than a solution
[EDIT] my two clones were faster than ;)
[EDIT] To be complete. Another implentation of clone() can be
#Override
public AClonable clone(){
try {
ByteArrayOutputStream outByte = new ByteArrayOutputStream();
ObjectOutputStream outObj = new ObjectOutputStream(outByte);
ByteArrayInputStream inByte;
ObjectInputStream inObject;
outObj.writeObject(this);
outObj.close();
byte[] buffer = outByte.toByteArray();
inByte = new ByteArrayInputStream(buffer);
inObject = new ObjectInputStream(inByte);
#SuppressWarnings("unchecked")
Object deepcopy = inObject.readObject();
inObject.close();
return (AClonable) deepcopy;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
when your abstract class implements Serialazable. There you write your object to disc and create a copy with the value from the disc.
You can't create deep clone of abstract class because they can't be instantiated. All you can do is shallow cloning by using Object.clone() or returning this
#Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
or
#Override
public Object clone() throws CloneNotSupportedException {
return this;
}
An abstract class can act as a reference, and it cannot have an instance so shallow cloning works in this case
OR
As a better approach, you can declare clone() as abstract and ask child class to define it, something like this
abstract class Shape {
private String str;
public Shape(String str) {
this.str = str;
}
public abstract Shape clone();
public String toString() {
return str;
}
}
class Circle extends Shape {
public Circle(String str) {
super(str);
}
#Override
public Shape clone() {
return new Circle("circle");
}
}
Although I doubt it is a good idea, you could use reflection:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test {
public static void main(String[] args) {
Square s1 = new Square("test");
Square s2 = (Square) s1.clone();
// show that s2 contains the same data
System.out.println(s2);
// show that s1 and s2 are really different objects
System.out.println(s1 == s2);
}
public static abstract class Shape {
private String str;
public Shape(String str) {
this.str = str;
}
public Shape clone() {
try {
Class<?> cl = this.getClass();
Constructor<?> cons = cl.getConstructor(String.class);
return (Shape) cons.newInstance(this.toString());
} catch (NoSuchMethodException | SecurityException |
InstantiationException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
#Override
public String toString() {
return str;
}
}
public static class Square extends Shape {
public Square(String str) {
super(str);
}
}
}
You can resolve with reflection:
public abstract class Shape {
private String str;
public Shape() {
}
protected Shape(String str) {
this.str = str;
}
public Shape clone() throws CloneNotSupportedException
{
try {
return (Shape)getClass().getDeclaredConstructor(String.class).newInstance(this.toString());
} catch (Exception e) {
throw new CloneNotSupportedException();
}
}
public String toString() {
return "shape";
}
public class Round extends Shape
{
public Round()
{
super();
}
protected Round(String str) {
super(str);
}
#Override
public String toString() {
return "round";
}
}
main(){
Shape round = new Round();
Shape clone = round.clone();
System.out.println(round);
System.out.println(clone);
}
but - IMO - is a poor implementation and error-prone with a lot of pits; the best use of Cloneable and Object.clone() is to not use them! You have a lot of way to do the same thing (like serialization for deep-clone) and shallow-clone that allow your a better control of flow.

Binding in JavaFX 2.0

Maybe I missunderstood JavaFX binding or there is a bug in SimpleStringProperty.
When I run this testcode my changed model value didn't get the new value. Test testBindingToModel fails. I thought my model should then be updated with the value of the TextField tf. But only the binding value of prop1Binding gets the value "test".
public class BindingTest {
private TextField tf;
private Model model;
private ModelBinding mb;
#Before
public void prepare() {
tf = new TextField();
model = new Model();
mb = new ModelBinding(model);
Bindings.bindBidirectional(tf.textProperty(), mb.prop1Binding);
}
#Test
public void testBindingToMB() {
tf.setText("test");
assertEquals(tf.getText(), mb.prop1Binding.get());
}
#Test
public void testBindingToModel() {
tf.setText("test");
assertEquals(tf.getText(), mb.prop1Binding.get());
assertEquals(tf.getText(), model.getProp1());
}
private static class ModelBinding {
private final StringProperty prop1Binding;
public ModelBinding(Model model) {
prop1Binding = new SimpleStringProperty(model, "prop1");
}
}
private static class Model {
private String prop1;
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
}
}
Thanks for your help.
Best regards
Sebastian
EDIT:
With this class I can set the value of the model directly. I will test this class in the next days and comment on this post with my result.
public class MySimpleStringProperty extends SimpleStringProperty {
public MySimpleStringProperty(Object obj, String name) {
super(obj, name);
}
public MySimpleStringProperty(Object obj, String name, String initVal) {
super(obj, name, initVal);
}
#Override
public void set(String arg0) {
super.set(arg0);
if (this.getBean() != null) {
try {
Field f = this.getBean().getClass().getDeclaredField(this.getName());
f.setAccessible(true);
f.set(this.getBean(), arg0);
} catch (NoSuchFieldException e) {
// logging here
} catch (SecurityException e) {
// logging here
} catch (IllegalArgumentException e) {
// logging here
} catch (IllegalAccessException e) {
// logging here
}
}
}
}
This constructor doesn't attach SimpleStringProperty to a bean object unfortunately. It just says to SimpleStringProperty which bean property belongs to.
E.g., if you want to have a property in your class you should do it next way:
public static class Model {
private StringProperty prop1 =
new SimpleStringProperty(this, "prop1", "default_value");
public String getProp1() {
return prop1.get();
}
public void setProp1(String value) {
prop1.set(value);
}
public StringProperty prop1Property() {
return prop1;
}
}
Note, that there is no way to bind to your original Model class as it provides no events about setting new prop1 value. If you want to have observable model, you should use fx properties from the beginning.
Just figured out that there is provided the class JavaBeanStringProperty, which just fullfill my request.
Using this code I can directly bind the value of my bean to a StringProperty (included setting and getting of my value to / from my Bean).
binding = JavaBeanStringPropertyBuilder.create().beanClass(Model.class).bean(model).name("prop1").build();
The only problem I found is that when you change the value of the model after setting the binding, there is no update e.g. in the TextField.

Categories