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