Consistent entity updates without exposing JpaTemplate

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Consistent entity updates without exposing JpaTemplate

Jens Offenbach
Hallo,
I am sorry, but I am still in trouble with JpaTemplate and API design. I am trying to hide JpaTemplate in my service implementation, but I am not sure, if this is the recommended approach. Unfortuantely, I cannot find any complex examples in the web.

Let me explain the problem with the help of the TaskService example (https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java):

Task task = taskService.getTask(1);
task.setTitle("New Title#1");

Both calls must be done under transaction control to keep the database consistent (Thanks Christian), so the only correct way would be:

jpa.tx(em -> {
    Task task = taskService.getTask(1);
    task.setTitle("New Title#1");
});

The problem is, that service users must have the JpaTemplate reference for consistent entity updates. The only way to hide JpaTemplate would be to extend TaskService like this:

public interface TaskService {

    void tx(Runnable runnable);

    Task getTask(Integer id);

    void addTask(Task task);

    void updateTask(Task task);

    void deleteTask(Integer id);
   
    Collection<Task> getTasks();

}

@Component
public class TaskServiceImpl implements TaskService {

    @Reference(target = "(osgi.unit.name=tasklist)")
    private JpaTemplate jpa;

    @Override
    public void tx(Runnable runnable) {
        jpa.tx(em -> runnable.run());
    }

}

The resulting user code that updates an entity consistently (hopefully) would look like this:

@Component(immediate = true)
public class TasklistUpdater {

    @Reference
    TaskService taskService;

    @Activate
    public void addDemoTask() {
        if (taskService.getTask(1) == null) {
            Task task = new Task();
            task.setId(1);
            task.setTitle("Task1");
            taskService.addTask(task);
        }
        updateDemoTask();
    }

    private void updateDemoTask() {
        taskService.tx(() -> {
            Task task = taskService.getTask(1);
            task.setDescription("A description");
            task.setTitle("A title");
        });
    }

}

I am not sure, if this approach works as expected and if JpaTemplate calls can be nested as shown above. What about overhead?

Are there any best practices known regarding API design in respect to JpaTemplate?

I am thankful for any comments or ideas for improvement?

Thank you very much,
Jens

Reply | Threaded
Open this post in threaded view
|

Re: Consistent entity updates without exposing JpaTemplate

Christian Schneider
For now this is a good pattern. I plan to add  a pure TransactionTemplate or similar to cover this case outside of JPATemplate.

Alternatively you can inject a UserTransaction and use it to create the transaction.

Christian

2017-04-21 16:49 GMT+02:00 Jens Offenbach <[hidden email]>:
Hallo,
I am sorry, but I am still in trouble with JpaTemplate and API design. I am trying to hide JpaTemplate in my service implementation, but I am not sure, if this is the recommended approach. Unfortuantely, I cannot find any complex examples in the web.

Let me explain the problem with the help of the TaskService example (https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java):

Task task = taskService.getTask(1);
task.setTitle("New Title#1");

Both calls must be done under transaction control to keep the database consistent (Thanks Christian), so the only correct way would be:

jpa.tx(em -> {
    Task task = taskService.getTask(1);
    task.setTitle("New Title#1");
});

The problem is, that service users must have the JpaTemplate reference for consistent entity updates. The only way to hide JpaTemplate would be to extend TaskService like this:

public interface TaskService {

    void tx(Runnable runnable);

    Task getTask(Integer id);

    void addTask(Task task);

    void updateTask(Task task);

    void deleteTask(Integer id);

    Collection<Task> getTasks();

}

@Component
public class TaskServiceImpl implements TaskService {

    @Reference(target = "(osgi.unit.name=tasklist)")
    private JpaTemplate jpa;

    @Override
    public void tx(Runnable runnable) {
        jpa.tx(em -> runnable.run());
    }

}

The resulting user code that updates an entity consistently (hopefully) would look like this:

@Component(immediate = true)
public class TasklistUpdater {

    @Reference
    TaskService taskService;

    @Activate
    public void addDemoTask() {
        if (taskService.getTask(1) == null) {
            Task task = new Task();
            task.setId(1);
            task.setTitle("Task1");
            taskService.addTask(task);
        }
        updateDemoTask();
    }

    private void updateDemoTask() {
        taskService.tx(() -> {
            Task task = taskService.getTask(1);
            task.setDescription("A description");
            task.setTitle("A title");
        });
    }

}

I am not sure, if this approach works as expected and if JpaTemplate calls can be nested as shown above. What about overhead?

Are there any best practices known regarding API design in respect to JpaTemplate?

I am thankful for any comments or ideas for improvement?

Thank you very much,
Jens




--
--
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Aw: Re: Consistent entity updates without exposing JpaTemplate

Jens Offenbach
Thanks Christian! That are good news... Especially, your future planning regarding "TransactionTemplate" sounds really interesting.

Can you plase provide a small example for your alternative solutions. How can I obtain a "UserTransaction" to create the transaction?

Best regards,
Jens

Gesendet: Samstag, 22. April 2017 um 13:22 Uhr
Von: "Christian Schneider" <[hidden email]>
An: [hidden email]
Betreff: Re: Consistent entity updates without exposing JpaTemplate

For now this is a good pattern. I plan to add  a pure TransactionTemplate or similar to cover this case outside of JPATemplate.
 
Alternatively you can inject a UserTransaction and use it to create the transaction.
 
Christian
 
2017-04-21 16:49 GMT+02:00 Jens Offenbach <[hidden email][mailto:[hidden email]]>:Hallo,
I am sorry, but I am still in trouble with JpaTemplate and API design. I am trying to hide JpaTemplate in my service implementation, but I am not sure, if this is the recommended approach. Unfortuantely, I cannot find any complex examples in the web.

Let me explain the problem with the help of the TaskService example (https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java[https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java]):

Task task = taskService.getTask(1);
task.setTitle("New Title#1");

Both calls must be done under transaction control to keep the database consistent (Thanks Christian), so the only correct way would be:

jpa.tx(em -> {
    Task task = taskService.getTask(1);
    task.setTitle("New Title#1");
});

The problem is, that service users must have the JpaTemplate reference for consistent entity updates. The only way to hide JpaTemplate would be to extend TaskService like this:

public interface TaskService {

    void tx(Runnable runnable);

    Task getTask(Integer id);

    void addTask(Task task);

    void updateTask(Task task);

    void deleteTask(Integer id);

    Collection<Task> getTasks();

}

@Component
public class TaskServiceImpl implements TaskService {

    @Reference(target = "(osgi.unit.name[http://osgi.unit.name]=tasklist)")
    private JpaTemplate jpa;

    @Override
    public void tx(Runnable runnable) {
        jpa.tx(em -> runnable.run());
    }

}

The resulting user code that updates an entity consistently (hopefully) would look like this:

@Component(immediate = true)
public class TasklistUpdater {

    @Reference
    TaskService taskService;

    @Activate
    public void addDemoTask() {
        if (taskService.getTask(1) == null) {
            Task task = new Task();
            task.setId(1);
            task.setTitle("Task1");
            taskService.addTask(task);
        }
        updateDemoTask();
    }

    private void updateDemoTask() {
        taskService.tx(() -> {
            Task task = taskService.getTask(1);
            task.setDescription("A description");
            task.setTitle("A title");
        });
    }

}

I am not sure, if this approach works as expected and if JpaTemplate calls can be nested as shown above. What about overhead?

Are there any best practices known regarding API design in respect to JpaTemplate?

I am thankful for any comments or ideas for improvement?

Thank you very much,
Jens
  
 --

--
Christian Schneider
http://www.liquid-reality.de[https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.liquid-reality.de]

Open Source Architect
http://www.talend.com[https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.talend.com]
Reply | Threaded
Open this post in threaded view
|

Re: Re: Consistent entity updates without exposing JpaTemplate

Yogesh Rao
Hello Jens,

You could try using Aries Transaction Control Service => http://aries.apache.org/modules/tx-control/ instead of injecting jpaTemplate

Regards,
-Yogesh

On Sat, 22 Apr 2017 at 8:38 PM, Jens Offenbach <[hidden email]> wrote:
Thanks Christian! That are good news... Especially, your future planning regarding "TransactionTemplate" sounds really interesting.

Can you plase provide a small example for your alternative solutions. How can I obtain a "UserTransaction" to create the transaction?

Best regards,
Jens

Gesendet: Samstag, 22. April 2017 um 13:22 Uhr
Von: "Christian Schneider" <[hidden email]>
An: [hidden email]
Betreff: Re: Consistent entity updates without exposing JpaTemplate

For now this is a good pattern. I plan to add  a pure TransactionTemplate or similar to cover this case outside of JPATemplate.
 
Alternatively you can inject a UserTransaction and use it to create the transaction.
 
Christian
 
2017-04-21 16:49 GMT+02:00 Jens Offenbach <[hidden email][mailto:[hidden email]]>:Hallo,
I am sorry, but I am still in trouble with JpaTemplate and API design. I am trying to hide JpaTemplate in my service implementation, but I am not sure, if this is the recommended approach. Unfortuantely, I cannot find any complex examples in the web.

Let me explain the problem with the help of the TaskService example (https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java[https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java]):

Task task = taskService.getTask(1);
task.setTitle("New Title#1");

Both calls must be done under transaction control to keep the database consistent (Thanks Christian), so the only correct way would be:

jpa.tx(em -> {
    Task task = taskService.getTask(1);
    task.setTitle("New Title#1");
});

The problem is, that service users must have the JpaTemplate reference for consistent entity updates. The only way to hide JpaTemplate would be to extend TaskService like this:

public interface TaskService {

    void tx(Runnable runnable);

    Task getTask(Integer id);

    void addTask(Task task);

    void updateTask(Task task);

    void deleteTask(Integer id);

    Collection<Task> getTasks();

}

@Component
public class TaskServiceImpl implements TaskService {

    @Reference(target = "(osgi.unit.name[http://osgi.unit.name]=tasklist)")
    private JpaTemplate jpa;

    @Override
    public void tx(Runnable runnable) {
        jpa.tx(em -> runnable.run());
    }

}

The resulting user code that updates an entity consistently (hopefully) would look like this:

@Component(immediate = true)
public class TasklistUpdater {

    @Reference
    TaskService taskService;

    @Activate
    public void addDemoTask() {
        if (taskService.getTask(1) == null) {
            Task task = new Task();
            task.setId(1);
            task.setTitle("Task1");
            taskService.addTask(task);
        }
        updateDemoTask();
    }

    private void updateDemoTask() {
        taskService.tx(() -> {
            Task task = taskService.getTask(1);
            task.setDescription("A description");
            task.setTitle("A title");
        });
    }

}

I am not sure, if this approach works as expected and if JpaTemplate calls can be nested as shown above. What about overhead?

Are there any best practices known regarding API design in respect to JpaTemplate?

I am thankful for any comments or ideas for improvement?

Thank you very much,
Jens
  
 --

--
Christian Schneider
http://www.liquid-reality.de[https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.liquid-reality.de]

Open Source Architect
http://www.talend.com[https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.talend.com]
Reply | Threaded
Open this post in threaded view
|

Re: Re: Consistent entity updates without exposing JpaTemplate

Christian Schneider
Aries transaction control is an option but you have to completely switch then.
Unfortunately tx control is not compatible to JPATemplate.

Christian

2017-04-23 2:18 GMT+02:00 Yogesh Rao <[hidden email]>:
Hello Jens,

You could try using Aries Transaction Control Service => http://aries.apache.org/modules/tx-control/ instead of injecting jpaTemplate

Regards,
-Yogesh

On Sat, 22 Apr 2017 at 8:38 PM, Jens Offenbach <[hidden email]> wrote:
Thanks Christian! That are good news... Especially, your future planning regarding "TransactionTemplate" sounds really interesting.

Can you plase provide a small example for your alternative solutions. How can I obtain a "UserTransaction" to create the transaction?

Best regards,
Jens

Gesendet: Samstag, 22. April 2017 um 13:22 Uhr
Von: "Christian Schneider" <[hidden email]>
An: [hidden email]
Betreff: Re: Consistent entity updates without exposing JpaTemplate

For now this is a good pattern. I plan to add  a pure TransactionTemplate or similar to cover this case outside of JPATemplate.
 
Alternatively you can inject a UserTransaction and use it to create the transaction.
 
Christian
 
2017-04-21 16:49 GMT+02:00 Jens Offenbach <[hidden email][mailto:[hidden email]]>:Hallo,
I am sorry, but I am still in trouble with JpaTemplate and API design. I am trying to hide JpaTemplate in my service implementation, but I am not sure, if this is the recommended approach. Unfortuantely, I cannot find any complex examples in the web.

Let me explain the problem with the help of the TaskService example (https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java[https://github.com/apache/aries/blob/trunk/jpa/examples/tasklist-ds/src/main/java/org/apache/aries/jpa/example/tasklist/ds/impl/TaskServiceImpl.java]):

Task task = taskService.getTask(1);
task.setTitle("New Title#1");

Both calls must be done under transaction control to keep the database consistent (Thanks Christian), so the only correct way would be:

jpa.tx(em -> {
    Task task = taskService.getTask(1);
    task.setTitle("New Title#1");
});

The problem is, that service users must have the JpaTemplate reference for consistent entity updates. The only way to hide JpaTemplate would be to extend TaskService like this:

public interface TaskService {

    void tx(Runnable runnable);

    Task getTask(Integer id);

    void addTask(Task task);

    void updateTask(Task task);

    void deleteTask(Integer id);

    Collection<Task> getTasks();

}

@Component
public class TaskServiceImpl implements TaskService {

    @Reference(target = "(osgi.unit.name[http://osgi.unit.name]=tasklist)")
    private JpaTemplate jpa;

    @Override
    public void tx(Runnable runnable) {
        jpa.tx(em -> runnable.run());
    }

}

The resulting user code that updates an entity consistently (hopefully) would look like this:

@Component(immediate = true)
public class TasklistUpdater {

    @Reference
    TaskService taskService;

    @Activate
    public void addDemoTask() {
        if (taskService.getTask(1) == null) {
            Task task = new Task();
            task.setId(1);
            task.setTitle("Task1");
            taskService.addTask(task);
        }
        updateDemoTask();
    }

    private void updateDemoTask() {
        taskService.tx(() -> {
            Task task = taskService.getTask(1);
            task.setDescription("A description");
            task.setTitle("A title");
        });
    }

}

I am not sure, if this approach works as expected and if JpaTemplate calls can be nested as shown above. What about overhead?

Are there any best practices known regarding API design in respect to JpaTemplate?

I am thankful for any comments or ideas for improvement?

Thank you very much,
Jens
  
 --

--
Christian Schneider
http://www.liquid-reality.de[https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.liquid-reality.de]

Open Source Architect
http://www.talend.com[https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.talend.com]



--
--
Christian Schneider
http://www.liquid-reality.de

Open Source Architect
http://www.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: Re: Consistent entity updates without exposing JpaTemplate

mit_jones
Hi Christian,

what is your long term goal for the JpaTemplate API? I am not clear how it will fit in with the current Aries ecosystem e.g. do you see it as an alternative to tx-control? Would it be possible to clarify what functionality overlaps and differs when compared to tx-control.

For example a small comparison matrix would make it easy for a potential adopter to compare the two (assuming you think that we are comparing apples with apples, I am not clear on this point). At this current point in time I believe tx-control offers the following

                            JDBC  JPA   XA tran  Local tran  Declarative Service  Blueprint  CDI   Specification   Comprehensive
                                                                                                                                                          Test Suite
tx-control               Y         Y       Y          Y              Y                            N             N      RFC 221         Y
JpaTemplate          ?         ?        ?          ?               ?                            ?              ?       ?                    ?



Thanks,

Tim