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 <[email protected]>:

> 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
<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 via email to