Recently I discovered ActiveObejcts and I really like it. Right now I'm using the last version from Atlassian plugin, only the net.java.ao part for ORM. Compiles and runs fine. Sure, I have to do some performance tests, if it fits my requirements.
There exists the #Implementation annotation. How is that used? The javadocs are very brief.
Update
Solution:
public class M5 {
public static void main(String[] args) throws SQLException {
EntityManager m = EntityManagerBuilder
.url("jdbc:hsqldb:./db/db")
.username("root")
.password("")
.c3po()
.build();
m.migrate(Employee.class);
Employee p = m.create(Employee.class);
p.setFirstName("Peter");
p.setLastName("Mmm");
System.err.println(p.getLastName()); // prints "ln: Mmm"
p.save();
}
}
public class Emp {
private Employee employee;
public Emp(Employee employee) {
this.employee = employee;
}
public String getLastName() {
return "ln: " + employee.getLastName();
}
}
#Implementation(Emp.class)
interface Employee extends Entity {
String getFirstName();
void setFirstName(String name);
String getLastName();
void setLastName(String name);
}
}
Active Objects takes your interface and, via reflection through a complicated proxy translates your getters, setters and relations into SQL statements. If you want some of your own code in there to add or modify functionality of your AO interface, you can use #Implementation
Example:
AO interface:
#Implementation(PersonImpl.class)
public interface Person extends Entity {
String getLastName();
void setLastName(String name);
String getFirstName();
void setFirstName(String name);
#Ignore
String getName();
}
Implementation:
public class PersonImpl {
private final Person person; // this will be the original entity proxy
public PersonImpl(Person person) {
this.person = person;
}
// "Implement" ignored functions
public String getName() {
return String.format("%s %s", this.person.getFirstName(), this.person.getLastName());
}
// "Enhance" AO getters/setters
public void setFirstName(String name) {
this.person.setFirstName("Foobar");
}
}
Note that AO accesses these implementation methods via reflection. They must match the names in the interface. This might lead to problems during refactorings, as method names might change and your compiler won't tell you that your corresponding impl method name hasn't.
Related
Recently I came into a situation where the builder pattern was very strong, but I had the need to subclass. I looked up some solutions and some suggested generics while others suggested normal subclassing. However, none of the examples I looked at had required fields in order to even begin building an object. I wrote a tiny example to illustrate where I'm getting stuck. At every turn I kept running into a wall of problems where things would return the wrong class, can't override static methods, returning super() returns the wrong data type, etc. I have a feeling there is no way out except excessive use of generics.
What is the correct way to go in this situation?
Tester
import person.Person;
import person.Student;
public class Tester
{
public static void main(String[] args)
{
Person p = Person.builder("Jake", 18).interest("Soccer").build();
// Student s = Student.builder(name, age) <-- It's weird that we still have access to pointless static method
// Student s = Student.builder("Johnny", 24, "Harvard", 3).address("199 Harvard Lane") <-- returns Person builder, not student
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
}
}
Person Class
package person;
import java.util.ArrayList;
import java.util.List;
public class Person
{
// Required
protected String name;
protected int age;
// Optional
protected List<String> interests = new ArrayList<>();
protected String address = "";
protected Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public List<String> getInterests() { return interests; }
public String getAddress() { return address; }
// person.person does not allow builder construction
// unless all required fields are provided
/* Problem: I have to repeat the constructor fields here, very annoying */
public static Builder builder(String name, int age)
{
Person p = new Person(name, age);
return new Builder(p);
}
public static class Builder
{
Person reference;
protected Builder(Person reference)
{
this.reference = reference;
}
public Builder address(String address)
{
reference.address = address;
return this;
}
public Builder interest(String interest)
{
reference.interests.add(interest);
return this;
}
public Person build()
{
return reference;
}
}
}
Student Class
package person;
import java.util.ArrayList;
import java.util.List;
public class Student extends Person
{
// Required
protected String school;
protected int year;
// Optional
protected List<String> subjects = new ArrayList<>();
// This looks good
public Student(final String name, final int age, final String school, final int year)
{
super(name, age);
this.school = school;
this.year = year;
}
public String getSchool() { return school; }
public int getYear() { return year; }
public List<String> getSubjects() { return subjects; }
/* Here's where my issues are:
* Override doesn't compile on static methods but how else can I describe that I want to
* override this functionality from the Person class?
*
* Extending 'Person' does not enforce that I need to provide 'name', 'age', etc like it would
* if this was a normal design pattern using the 'new' keyword. I have to manually drag fields
* from 'person' and place them here. This would get VERY messy with an additional class
*
* User can STILL call the Person builder on a Student object, which makes no sense. */
/*#Override*/ public static Builder builder(String name, int age, String school, int year)
{
Student s = new Student(name, age, school, year);
return new Builder(s);
}
public static class Builder extends Person.Builder
{
// Student reference; <--- this should not be needed since we already
// have a variable for this purpose from 'Person.Builder'
public Builder(final Student reference)
{
super(reference);
}
/* Things begins to get very messy here */
public Builder subject(String subject)
{
((Student)reference).subjects.add(subject);
// I guess I could replace the reference with a student one, but
// I feel like that infringes on calling super() builder since we do the work twice.
return this;
}
#Override public Student build()
{
// I can either cast here or
// rewrite 'return reference' every time.
// Seems to infringe a bit on subclassing.
return (Student)super.build();
}
}
}
What you write here :
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
is indeed not very natural and you should not need to cast.
We expect rather something like :
Student s = Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build();
Besides all casts you did in the implementation of Student.Builder are also noise and statements that may fail at runtime :
/* Things begins to get very messy here */
public Builder subject(String subject) {
((Student)reference).subjects.add(subject);
return this;
}
#Override public Student build() {
return (Student)super.build();
}
Your main issue is the coupling between the Builder classes and the building methods.
A important thing to consider is that at compile time, the method binding (method selected by the compiler) is performed according to the declared type of the target of the invocation and the declared type of its arguments.
The instantiated type is considered only at runtime as the dynamic binding is applied: invoking the method bounded at compile time on the runtime object.
So this overriding defined in Student.Builder is not enough :
#Override public Student build() {
return (Student)super.build();
}
As you invoke :
Student.builder("Jack", 19, "NYU", 1).address("Dormitory").build();
At compile time, address("Dormitory") returns a variable typed as Person.Builder as the method is defined in Person.Builder :
public Builder address(String address){
reference.address = address;
return this;
}
and it not overriden in Student.Builder.
And at compile time, invoking build() on a variable declared as Person.Builder returns a object with as declared type a Person as the method is declared in Person.Builder as :
public Person build(){
return reference;
}
Of course at runtime, the returned object will be a Student as
Student.builder("Jack", 19, "NYU", 1) creates under the hood a Student and not a Person.
To avoid cast to Student.builder both from the implementation and the client side, favor composition over inheritancy :
public static class Builder {
Person.Builder personBuilder;
private Student reference;
public Builder(final Student reference) {
this.reference = reference;
personBuilder = new Person.Builder(reference);
}
public Builder subject(String subject) {
reference.subjects.add(subject);
return this;
}
// delegation to Person.Builder but return Student.Builder
public Builder interest(String interest) {
personBuilder.interest(interest);
return this;
}
// delegation to Person.Builder but return Student.Builder
public Builder address(String address) {
personBuilder.address(address);
return this;
}
public Student build() {
return (Student) personBuilder.build();
}
}
You can now write :
Student s = Student.builder("Jack", 19, "NYU", 1)
.address("Dormitory")
.build();
or even that :
Student s2 = Student.builder("Jack", 19, "NYU", 1)
.interest("Dance")
.address("Dormitory")
.build();
Composition introduces generally more code as inheritancy but it makes the code
both more robust and adaptable.
As a side note, your actual issue is enough close to another question I answered 1 month ago.
The question and its answers may interest you.
A few thoughts as background
Static methods are not so great,
they make unit testing more difficult.
It is fine to put the builder as a static, nested class, but if you are using a builder to construct a class you should make the constructor not-public.
I prefer to have the builder be a separate class in the same package and to make the constructor (of the class that is created by the builder) package access.
Limit the builder constructor parameters.
I'm not a fan of using a class hierarchy for builders.
The Person and Student classes each have a builder.
Some Code
public class PersonBuilder
{
private String address;
private int age;
private final List<String> interestList;
private String name;
public PersonBuilder()
{
interestList = new LinkedList<>();
}
public void addInterest(
final String newValue)
{
// StringUtils is an apache utility.
if (StringUtils.isNotBlank(newValue))
{
interestList.add(newValue);
}
return this;
}
public Person build()
{
// perform validation here.
// check for required values: age and name.
// send all parameters in the constructor. it's not public, so that is fine.
return new Person(address, age, interestList, name);
}
public PersonBuilder setAddress(
final String newValue)
{
address = newValue;
return this;
}
public PersonBuilder setAge(
final int newValue)
{
age = newValue;
return this;
}
public PersonBuilder setInterestList(
final List<String> newValue)
{
interestList.clear();
if (CollectionUtils.isNotEmpty(newValue))
{
interestList.addAll(newValue);
}
return this;
}
public PersonBuilder setName(
final String newValue)
{
name = newValue;
return this;
}
}
public class Person
{
private Person()
{
}
Person(
final String addressValue,
final int ageValue,
final List<String> interestListValue,
final String name)
{
// set stuff.
// handle null for optional parameters.
}
// create gets or the fields, but do not create sets. Only the builder can set values in the class.
}
We are currently attempting to implement an extension to SlingModels, to allow a slingmodel to be persisted to the JCR directly.
Our strategy has 2 considered starting conditions:
1. A new object that is to be persisted
2. An object that has been retrieved from the JCR, altered, and is then to be persisted again
For situation 1, we are using reflection to examine the object, create a new node for the model, insert properties for any of the primitive variables found, and recursively use the same persistence approach for any complex model objects found as variables, and collections.
My question on best approach relates to situation 2. If we pull out an object from the repository, we cannot be guaranteed that the node will not be synchronously changed in the meantime. Thus, we would like to implement a change watcher on the SlingModel that keeps a transaction journal on any changes made. The transactions can then be used to set the relevant properties when persisting the object back to the JCR again.
I have considered using an observer pattern, but this would mean that we would need to implement a function within the setter on each SlingModel, which is not ideal at all, as it requires a developer to remember to add the code and do it correctly.
Ideally, I would like to implement something like an interceptor directly on the variable, or if not possible, on the setter itself, and mandate that each model would then need to use a getter/setter for each variable. We can configure code scanning tools to enforce developers to implement getter/setters.
What would the be the best way to approach the change watcher here?
import java.util.List;
public class Teacher {
private String userName;
private String cource;
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCource() {
return cource;
}
public void setCource(String cource) {
this.cource = cource;
}
}
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ClassFacadeCglib implements MethodInterceptor{
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// callback method
enhancer.setCallback(this);
// create proxy object
return enhancer.create();
}
#Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
if(method.getName().startsWith("set")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end..");
}
if(method.getName().startsWith("get")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end");
}
return null;
}
}
public class Main {
public static void main(String[] args) {
ClassFacadeCglib cglib=new ClassFacadeCglib();
Teacher teacher=(Teacher)cglib.getInstance(new Teacher());
teacher.setCource("Math");
teacher.getUserName();
}
}
Note :
cglib-full-2.0.2.jar is required for running.
see https://repo1.maven.org/maven2/cglib/cglib-full/2.0.2/
I have a case when I want to avoid defensive copies, for data which might nevertheless be modified, but is usually simply read, and not written to. So, I'd like to use immutable objects, with functional mutator methods, which is kind of usual (java lombok is able to do it more or less automatically). The way I proceed is the following:
public class Person {
private String name, surname;
public Person(String name, String surname) {....}
// getters...
// and instead of setters
public Person withName(String name) {
Person p= copy(); // create a copy of this...
p.name= name;
return p;
}
public Person copy() {....}
}
So, to get a copy of the person with a different name, I would call
p= new Person("Bar", "Alfred");
...
p= p.withName("Foo");
In practice, the objects are rather large (and I ended up using serialization to avoid the burden of writing the copy code).
Now, while browsing the web, I see a potential concurrency problem with this implementation, as my fields are not final, and thus, concurrent access might see the returned copy, for instance, without the new name change (as there is no warrantee on the order of operation in this context).
Of course, I can't make my fields final, with the current implementation, as I first do a copy, and then change the data in the copy.
So, I'm looking for a good solution for this problem.
I might use volatile, but I feel it's not a good solution.
Another solution would be to use the builder pattern:
class PersonBuilder {
String name, surname; ....
}
public class Person {
private final String name, surname;
public Person(PersonBuilder builder) {...}
private PersonBuilder getBuilder() {
return new PersonBuilder(name, surname);
}
public Person withName(String name) {
PersonBuilder b= getBuilder();
b.setName(name);
return new Person(b);
}
}
Is there any problem here, and above all, is there a more elegant way of doing the same thing ?
I recommend you take a look at Guava's immutable collections, such as immutable list and how they create lists from builders etc.
The idiom is the following:
List<String> list1 = ImmutableList.of("a","b","c"); // factory method
List<String> list2 = ImmutableList.builder() // builder pattern
.add("a")
.add("b")
.add("c")
.build();
List<String> list3 = ... // created by other means
List<String> immutableList3 = ImmutableList.copyOf(list3); // immutable copy, lazy if already immutable
I really like the idiom above. For an entity builder I would take the following approach:
Person johnWayne = Person.builder()
.firstName("John")
.lastName("Wayne")
.dob("05-26-1907")
.build();
Person johnWayneClone = johnWayne.copy() // returns a builder!
.dob("06-25-2014")
.build();
The builder here can be obtained from an existing instance via the copy() method or via a static method on the Person class (a private constructor is recommended) that return a person builder.
Note that the above mimics a little Scala's case classes in that you can create a copy from an existing instance.
Finally, don't forget to follow the guidelines for immutable classes:
make the class final or make all getters final (if the class can be extended);
make all fields final and private;
initialize all fields in the constructor (which can be private if you provide a builder and/or factory methods);
make defensive copies from getters if returning mutable objects (mutable collections, dates, third party classes, etc.).
One possibility is to separate your interfaces surrounding such objects into an immutable variant (providing getters) and a mutable variant (providing getters and setters).
public interface Person {
String getName();
}
public interface MutablePerson extends Person {
void setName(String name);
}
It doesn't solve the mutability of the object per se but it does offer some guarantees that when you pass around the object using the immutable interface reference, you know that the code you're passing this to won't change your object. Obviously you need to control the references to the underlying object and determine the subset of functionality that has control of a reference via the mutable interface.
It doesn't solve the underlying problem and I would favour immutable objects until I definitely need a mutable version. The builder approach works nicely, and you can integrate it within the object to give a modifier thus:
Person newPerson = existingPerson.withAge(30);
Why not make your fields final and your modifier methods directly create new objects?
public class Person {
private final String name, surname;
public Person(String name, String surname) {....}
// getters...
// and instead of setters
public Person withName(String newName) {
return new Person(newName, surname);
}
}
Your problem boils down to this: You want a method that safely publishes an effectively immutable, almost-but-not-quite-faithful copy of an effectively immutable object.
I'd go with the builder solution: It's verbose as all get out, but Eclipse helps with that, and it allows all of the published objects to be actually immutable. Actual immutability makes safe publication a no-brainer.
If I wrote it, it'd look like this:
class Person {
public static final FooType DEFAULT_FOO = ...;
public static final BarType DEFAULT_BAR = ...;
public static final BazType DEFAULT_BAZ = ...;
...
private final FooType foo;
private final BarType bar;
private final BazType baz;
...
private Person(Builder builder) {
this.foo = builder.foo;
this.bar = builder.bar;
this.baz = builder.baz;
...
}
public FooType getFoo() { return foo; }
public BarType getBar() { return bar; }
public BazType getBaz() { return baz; }
...
public Person cloneWith(FooType foo) {
return new Builder(this).setFoo(foo).build();
}
public Person cloneWith(BarType bar) {
return new Builder(this).setBar(bar).build();
}
public Person cloneWith(FooType foo, BarType bar) {
return new Builder(this).setFoo(foo).setBar(bar).build();
}
...
public class Builder{
private FooType foo;
private BarType bar;
private BazType baz;
...
public Builder() {
foo = DEFAULT_FOO;
bar = DEFAULT_BAR;
baz = DEFAULT_BAZ;
...
}
public Builder(Person person) {
foo = person.foo;
bar = person.bar;
baz = person.baz;
...
}
public Builder setFoo(FooType foo) {
this.foo = foo;
return this;
}
public Builder setBar(BarType bar) {
this.bar = bar;
return this;
}
public Builder setBaz(BazType baz) {
this.baz = baz;
return this;
}
...
public Person build() {
return new Person(this);
}
}
}
Depends on how many fields you intend to change. You could make special Changed objects like:
interface Person {
public String getForeName();
public String getSurName();
}
class RealPerson implements Person {
private final String foreName;
private final String surName;
public RealPerson (String foreName, String surName) {
this.foreName = foreName;
this.surName = surName;
}
#Override
public String getForeName() {
return foreName;
}
#Override
public String getSurName() {
return surName;
}
public Person setSurName (String surName) {
return new PersonWithSurnameChanged(this, surName);
}
}
class PersonWithSurnameChanged implements Person {
final Person original;
final String surName;
public PersonWithSurnameChanged (Person original, String surName) {
this.original = original;
this.surName = surName;
}
#Override
public String getForeName() {
return original.getForeName();
}
#Override
public String getSurName() {
return surName;
}
}
This may also mitigate the problem you have with cloning heavy objects.
This is the test class that I have an error in and I cant figure out what it is exactly.
import java.util.*;
public class EmployeeTest
{
public static void main(String[] args) {
Employee e = new Employee();
e.setId("100012");
e.setLastname("Smith");
ResponsibilityDecorator d;
d = new Recruiter(e);
d = new CommunityLiaison(e);
d = new ProductionDesigner(e);
System.out.println(e.toString());
}
}
And this the class that links to the test class
public class Employee
{
String id;
String lastname;
Employee(String id, String lastname)
{
this.id=id;
this.lastname=lastname;
}
EmploymentDuties eduties=new EmploymentDuties();
public EmploymentDuties getDuties()
{
return eduties;
}
public String toString(){
return "Duties for this employee: "+eduties.jobtitles;
}
public void setId(String id)
{
this.id = id;
}
public void setLastname(String lastname)
{
this.lastname = lastname;
}
}
There is no no-args constructor in Employee. Add parameters to use the existing constructor in EmployeeTest
Employee e = new Employee("100012", "Smith");
the statements
e.setId("100012");
e.setLastname("Smith");
are then redundant and can be removed.
Your class Employee defines exactly one constructor: Employee(String, String). Make sure you call it from the EmployeeTest or define a no parameter constructor.
The default constructor is the constructor provided by the java in the absence of any constructor provided by the you.
Once you supplies any constructor , the default constructor is no longer supplied.
you created constructor
Employee(String id, String lastname)
{
and using like
Employee e = new Employee(); //not possible
The default constructor is the no-argument constructor automatically generated unless you define another constructor.
This is the default constructor :
Employee() {}
Then you can instantiate objects like :
Employee e = new Employee();
if you define at least one constructor explicitly , the default constructor is not generated.
class Person {
String name = “No name";
public Person(String nm) { name = nm; }
}
class Employee extends Person {
String emplD = “0000”;
public Employee(String id) { empID = id; }
}
public class EmployeeTest {
public static void main(String[ ] args)
{
Employee e = new Employee(”4321”);
System.out.println(e.empID);
}
}
The constructor of Employee must call its super constructor, the constructor of Person.
public class Person
{
private String name;
public Person(String nm)
{
this.name = nm;
}
public String getName()
{
return this.name;
}
}
public class Employee extends Person
{
private String emplD;
public Employee(String nm, String id)
{
super(nm);
this.empID = id;
}
public String getId()
{
return this.empID;
}
}
public class EmployeeTest
{
public static void main(String[] args)
{
Employee e = new Employee("Some Name", "4321");
System.out.println(e.getID());
}
}
Change “No name’ into “No name" (closing quotes)
Maybe it's here:
String name = “No name’;
should it be:
String name = "No name";
Also, I'm not sure if this is the editor that you've pasted it in from doing this, but this is wrong too:
Employee e = new Employee(”4321”);
should be:
Employee e = new Employee("4321");
A number of things:
You're using the wrong kind of quote characters around your strings. You need to use ". Not “, ', or ”.
Your Person class has no default constructor. Because of this you must explicitly call super("some name"); as the first line of your Employee constructor (I would suggest adding a constructor that takes both name and employeeId as parameters).
You declared the property as emplD (with a lower-case L character), but you try to assign to it as empID (with an uppercase I character). You can call it whatever you want, but the name needs to match in both places.
Your object design violates the basic principles of encapsulation. The name and empID properties should be private fields, and if external classes need access to these values, then you should provide the appropriate public getter methods. In other words, instead of e.empID you should be able to say e.getEmpID().
It is generally not good coding style to define multiple classes in a single file, particularly when all of them are meant to be publicly accessible.
Change this line
String name = “No name’;
to:
String name = “No name";
check your closing qoutes.
Your empID field is not public / there is no accessor method for it / it is not defined as a property. Also don't expect people to help if you provide absolutely no information on the error other than the source code and a vague post title.
You have to call the constructor of the superclass (Person) in the constructor of the class `Employeesuper(id); Please find the correct code below.
public Employee(String id) {super(id);empID =id;
Calling a super class constructor would fix the issue !
public class Person {
String name = "No name";
public Person(String nm) { name = nm; }
}
public class Employee extends Person {
String empID = "0000";
public Employee(String id) {
super("Some Name");
empID = id; }
}
public class EmployeeTest {
public static void main(String[] args){
Employee e = new Employee("4321");
System.out.println(e.empID);
}
}