How am I misusing generics with commons beanutils? - java

I have two simple interfaces:
public interface HasId<ID extends Serializable> extends Serializable {
T getId();
}
And
public interface HasLongId extends HasId<Long> {
void setId(Long id);
}
Now, if I have a class:
public class Person implements HasLongId {
private Long id;
private String name;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
And I instantiate a person, then pass it to BeanUtils I get strange behavior. For example sometimes setting id using BeanUtils works fine and other times, I get an exception because it can't find the "write" method for Id. It seems that during reflection it finds a getter for a Serializable, but not a Long and it does not find a setter for the Serializable. It does not do this consistently, so I suspect that calling person.getClass().getDeclaredMethod("id") will not always return the same Method, but I could be wrong about that.
Anyway, this inconsistent behavior is really maddening because, for example, it will work in Eclipse, but not in Maven, or it will work for a long time and then with some unrelated change somewhere else it will stop working.
Clearly I don't understand generics well enough to understand what is happening, but can anyone explain it to me and also explain how to work around it?

The version of Apache Commons BeanUtils I have used was not Java 5 aware, so it didn't know about Generics, bridge methods, and so on. I believe that's the problem, which version of BeanUtils are you using? and is it Java 5+ aware?

I don't care much for this design - I don't like interfaces merely for getters and setters.
I also wouldn't have that interface extend Serializable; single responsibility is the best advice here.
But I would try it like this:
public interface Identifiable<T extends Serializable> {
T getId();
void setId(T newId);
}
public class Person implements Identifiable<Long> {
private Long id;
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
}

Related

Java - Event Sourcing - Event Sequence

So, while developing an app, I have to use event sourcing to track down all changes to model. The app itself is made using spring framework. The problem I encountered: for example, user A sends a command to delete an entity and it takes 1 second to complete this task. User B, at the same time, sends a request to modify, for example, an entity name and it takes 2 seconds to do so. So my program finishes deleting this entity (persisting an event that says this entity is deleted), and after it another event is persisted for the same entity, that says that we just modified its name. But no actions are allowed with deleted entities. Boom, we just broke the app logic. It seems to me, that I have to put methods that write to database in synchronized blocks, but is there are any other way to handle this issue? Like, I dunno, queuing events? The application is not huge, and not a lot of requests are expected, so users can wait for its request turn in the queue (of course I can return 202 HTTP Status Code to him, but like I said, requests are not resource heavy and there wont be a lot of them, so its unnecessary). So what is the best way for me to use here?
EDIT: Added code to illustrate the problem. Is using synchronized in this case is a good practice or there are other choices?
#RestController
#RequestMapping("/api/test")
public class TestController {
#Autowired
private TestCommandService testCommandService;
#RequestMapping(value = "/api/test/update", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void update(TestUpdateCommand command) {
testCommandService.update(command);
}
#RequestMapping(value = "/api/test/delete", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void delete(Long id) {
testCommandService.delete(id);
}
}
public class TestUpdateCommand {
private Long id;
private String name;
public TestUpdateCommand() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public interface TestCommandService {
void delete(Long id);
void update(TestRegisterCommand command);
}
#Service
public class TestCommandServiceImpl implements TestCommandService {
#Autowired
TestEventRepository testEventRepository;
#Override
#Transactional
public void delete(Long id) {
synchronized (TestEvent.class) {
//do logic, check if data is valid from the domain point of view. Logic is also in synchronized block
DeleteTestEvent event = new DeleteTestEvent();
event.setId(id);
testEventRepository.save(event);
}
}
#Override
#Transactional
public void update(TestUpdateCommand command) {
synchronized (TestEvent.class) {
//do logic, check if data is valid from the domain point of view. Logic is also in synchronized block
UpdateTestEvent event = new DeleteTestEvent();
event.setId(command.getId());
event.setName(command.getName());
testEventRepository.save(event);
}
}
}
#Entity
public abstract class TestEvent {
#Id
private Long id;
public Event() {
}
public Event(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
#Entity
public class DeleteTestEvent extends TestEvent {
}
#Entity
public class UpdateTestEvent extends TestEvent {
private String name;
public UpdateTestEvent() {
}
public UpdateTestEvent(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public interface TestEventRepository extends JpaRepository<TestEvent, Long>{
}
Make sure you read Don't Delete -- Just Don't by Udi Dahan.
I have to put methods that write to database in synchronized blocks, but is there are any other way to handle this issue?
Yes, but you have to be careful about identifying what the issue is...
In the simple version; as you have discovered, allowing multiple sources of "truth" can introduce a conflict. Synchronization blocks is one answer, but scaling synchronization is challenging.
Another approach is to use a "compare and swap approach" -- each of your writers loads the "current" copy of the state, calculates changes, and then swaps the new state for the "current" state. Imagine two writers, one trying to change state:A to state:B, and one trying to change state:A to state:C. If the first save wins the race, then the second save fails, because (A->C) isn't a legal write when the current state is B. The second writer needs to start over.
(If you are familiar with "conditional PUT" from HTTP, this is the same idea).
At a more advanced level, the requirement that the behavior of your system depends on the order that messages arrive is suspicious: see Udi Dahan's Race Conditions Don't Exist. Why is it wrong to change something after deleting it?
You might be interested in Martin Kleppmann's work on conflict resolution for eventual consistency. He specifically discusses examples where one writer edits an element that another writer deletes.

One class implements from two different interfaces in Java

I have two classes that implements from two interfaces.
Here is my interfaces:
interface Identifiable {
int getId();
}
interface Greetable {
String helloMessage();
String byeMessage();
}
Here is my classes:
public class Lecturer implements Greetable, Identifiable {
private int employeeId;
private String name;
private String title;
#Override
public String helloMessage() {
return name;
}
#Override
public String byeMessage() {
return title;
}
}
public class Student implements Greetable, Identifiable {
private char examScore;
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
}
I get the error from the classes that it has to abstract the methods from the interfaces? What does that mean?
Non-abstract classes are required to create concrete versions of any methods found in any interfaces that they're implementing, and while your classes implement concrete versions of one of the interface, the Greetable interface, you're not implementing all the methods of both interfaces, here the public int getId() method from the Identifiable interface is missing from both classes.
Solution: give both classes an int id field as well as the getId() method that returns the value held by this field.
e.g. for Student,
public class Student implements Greetable, Identifiable {
private char examScore;
private int id; // **** your classes will need this field ****
// need to set the ID somehow, either with a setter or a constructor
public Student(int id) {
this.id = id;
}
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
#Override // **************** add this method to return the value held by id ******
public int getId() {
return this.id;
}
}
You define to implement both interfaces, but you only implemented the methods of the second interface.
So you have to implement the method getId() in both classes.
You havent implemeted the getId() method in Identifiable. If you are not implementing that method you need to make the Lecturer and Student as abstract or you need to implement the getId() method in both the classes.
In your case I think you will need to create instances of the Student and Lecturer. If so then you cannot make them as abstract, as abstract class instances cannot be created. So better implement the getId() in both the classes.
Your Student and Lecturer classes MUST implement both Greetable, Identifiable interface methods, otherwise they need to be declared as abstract classes i.e., you are missing getId() from Identifiable interface, which is causing the issues, corrected code below.
Lecturer class:
public class Lecturer implements Greetable, Identifiable {
int getId() {
return employeeId;
}
//all other existing methods
}
Student class:
public class Student implements Greetable, Identifiable {
int getId() {
return studentId;
}
//all other existing methods
}
You can look here

save mongo entity to the different collections

I've been using Spring Data for saving entities to the mongo DB and my code at the moment looks like this:
I have a repo class:
public interface LogRepo extends MongoRepository<Log, String> {
}
and I have an Entity Log which looks like this:
#Document(
collection = "logs"
)
public class Log {
#Id
private String id;
private String jsonMessage;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJsonMessage() {
return jsonMessage;
}
public void setJsonMessage(String jsonMessage) {
this.jsonMessage = jsonMessage;
}
}
and this work well for me, however this approach works only for the case if I want to save Log entities to "logs" collection. However it would be very nice for me to be able to save Log entity to different collections depending on the context. I mean it would be nice to define collection name in the runtime. Is it possible somehow?
Thanks, cheers
Try to use inheritance and define appropriate collection names in such way. May give you possibility to save in different collections but you will be still not able to specify dynamically collection names and resp. their amount at runtime.
#Document(
collection = "logs"
)
public class Log {
#Id
private String id;
private String jsonMessage;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJsonMessage() {
return jsonMessage;
}
public void setJsonMessage(String jsonMessage) {
this.jsonMessage = jsonMessage;
}
}
#Document(
collection = "log_child"
)
public class LogChild extends Log{}
With the MongoOperations save method you can choose which class to use and
based on the class it will choose the appropriate collection.
#Document(collection = "collection_#{T(com.github.your_project.DBUtils).getCollectionName()}")
public Class Collection
You can change the name in real time using a static getter
#UtilityClass
public class DBUtils {
private String collectionName;
public String getCollectionName() {
return collectionName;
}
public void setCollectionName(String collectionName) {
DBUtils.collectionName = collectionName;
}
}

Java wrapper class subclass of concrete type

Let's say I have a class person as follows:
public class Person {
String name;
int age;
}
and a number of subclasses such as
public class Student extends Person {
// extra fields and methods
}
public class Teacher extends Person {
// extra fields and methods
}
Now, consider that for some application I need to assign an integer id to each person instance, but I don't want to extend the Person interface to add the getId() there and a field to hold the id. A simple solution would be to use a wrapper like:
public class PersonWrapper extends Person {
public PersonWrapper(Person p, int id) { // assign the id and other fields }
public int getId() { return id; }
}
This way the client code still works with the Person interface and a wrapped person can be
treated as a person.
The problem with this approach is that PersonWrapper is a subclass of Person and not Teacher or Student, and such a code won't work:
Teacher t = new PersonWrapper(teacher, 1);
t.giveGrade();
Of course, it's possible to create concrete wrapper types for all subclasses of Person, but I was wondering if there is a more elegant solution. The ideal solution would be something like this:
public class PersonWrapper<T extends Person> extends T
so that any PersonWrapper is a subclass of the type it wraps, but it's not possible in Java and I
suspect such definition may not be possible in any language.
In any case, how can I assign ids to subclasses without changing my client code that works with person and its subclasses, without creating a concrete wrapper for each subclass?
A wrapper does not necessarily need to extend to the class it's wrapping. So, just use PersonWrapper<T extends Person>:
public class PersonWrapper<T extends Person> {
T person;
int id;
public PersonWrapper(T person, int id) {
this.person = person;
this.id = id;
}
//getters and setters...
}
Also, a class can only extend from another class at compile time, so it's not possible that this PersonWrapper could extend from Student and Teacher at the same time, which makes impossible what you're looking for.
The only solution would be creating proxy classes on the fly using a library like cglib. For example, Spring creates proxies for classes when needs to add functionality on the fly to a class e.g. adding transaction management for methods or whole class.
The common solution to this problem is to make Person an interface.
interface Person {
public String getName();
public int getAge();
}
class ActualPerson implements Person {
private final String name;
private final int age;
ActualPerson(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String getName() {
return name;
}
#Override
public int getAge() {
return age;
}
}
class PersonWithId implements Person {
private final Person person;
private final int id;
PersonWithId(Person person, int id) {
this.person = person;
this.id = id;
}
#Override
public String getName() {
return person.getName();
}
#Override
public int getAge() {
return person.getAge();
}
}
Do not fear lots of code - the time you take writing code is insignificant compared to the time you spend regretting you didn't do it properly in the first place. Old Curmudgeon 2014
You're right that you can't do what you want to do. Assuming that you can't change the concrete classes to be, say, Student extends Person implements Identifiable, your best bet is to treat your wrapper really as a wrapper, and have a getter that returns its different elements:
public class Wrapper<T> {
private final T item;
private final int id;
...
public int getId() { return id }
public T getItem() { return item; }
}
This is a bit cumbersome to use, because you have to do something like wrapper.getItem().giveGrade() instead of just wrapper.giveGrade(). It also means you can't shove the wrapper into a List<Teacher> and then later downcast it to TeacherWrapper -- but that's a bit fragile, and there are often better ways to accomplish what you want. For most cases, this "pure" wrapper approach will do what you want.
Note that I didn't even have T extends Person. If the wrapper class doesn't need to use any Person methods, there's not much to gain from artificially restrict the generic. The call sites will all have the restriction either way. The one difference is that if a call site has a Wrapper<?>, then my code will only let you get the item as an Object, whereas the more restrictive T extends Person will let you get that item as a Person.
I hope I'm not missing something, but it appears to me that the wrapper pattern solves your problem:
public class Person implements IPerson{
String name;
int age;
public static void main(String[] args)
{
Teacher teacherWithID = new Teacher(new PersonWithID(new Person()));
Teacher teacherWithoutID = new Teacher(new Person());
}
}
interface IPerson{}
class Teacher implements IPerson{
public Teacher(IPerson personToBeWrapped){}
}
class Student implements IPerson{
public Student(IPerson personToBeWrapped){}
}
class PersonWithID implements IPerson{
public PersonWithID(IPerson personToBeWrapped){}
}
Whatever type your variable is should be the last wrapper.
The wrapper pattern can be considered to be a mechanic that allows you to "extend" classes at runtime. It's also called the decorator for that reason. You have competing inheritance mechanics in your code. (the built in one and the pattern) The result is that you cannot type your variable.
If you use the pattern exclusively, it works.

Java - Generic variable becomes java.lang.Object when looking through reflection

I have a generic class as follows:
public MyClass<T>{
T id;
public T getId(){return id;}
public void setId(T id){this.id=id;}
}
I instantiate it as follows:
MyClass<String> myClass = new MyClass<String>();
When looking the getId() method through reflection (i == the index of the getId method):
myClass.getClass().getMethods()[i].getReturnType();
It will say that the return type is java.lang.Object.
I'm guessing I'm asking the impossible here, but, would it somehow be possible for the class to actually say java.lang.String in this case?
The reason I'm asking this is because I'm using App engine and it's Datastore. A simplified scenario: I got all my classes inheriting from MyClass and therefore they get a id with the type T, where T is either Long, String or Key. But the datastore thinks no matter what that the id field is an java.lang.Object, which is prohibited. Do I need to make classes like MyClassString, MyClassLong etc, or is there some way i can bypass this?
Thank you!
EDIT: After searching for another issue I had after "solving" this. I found this question actually mentioning my exact problem.
The type arguments for the parameterized type are lost at runtime through a process known as type erasure. At runtime there is no way to determine the method returns a String, since the actual type arguments used are not available.
Generic Faq
One way to work around this would be implement a generic interface, which would allow the objects to be used in a polymorphic manner:
Identifiable.java
public interface Identifiable<T> {
T getId();
void setId(T t);
}
Person.java
public class Person implements Identifiable<String> {
private String id;
#Override
public String getId() {
return id;
}
#Override
public void setId(String t) {
this.id = t;
}
public static void main(String[] args) {
Person person = new Person();
Method method = person.getClass().getMethods()[1]; //prints getId
System.out.println(method.getName());
System.out.println(method.getGenericReturnType()); //prints String
}
}
You could do this by storing a class variable within and returning this on request.
i.e.
public MyClass<T>{
Class<T> clazz;
T id;
public T getId(){return id;}
public void setId(T id){this.id=id;}
MyClass(Class<T> clazz) {
this.clazz=clazz
}
public Class<T> getIdClass() { return clazz; }
}
Now to find out what type your class is you can just call getIdClass() on it and use that returned type. Generics will enforce that the type is set correctly when an instance of MyClass is created.
A little modification can be added to Tim B's solution, if you do not want parametrized constructor.
public class MyClass<T>{
Class<T> clazz;
T id;
public T getId(){return id;}
public void setId(T id){this.id=id;}
public Class<?> getIdClass() {
if (id != null) {
return id.getClass();
} else {
return Object.class;
}
}
}
You can check it by
MyClass<String> myClass = new MyClass<String>();
myClass.setId("abc");
System.out.println(myClass.getIdClass());

Categories