Jörg Rade created CAUSEWAY-3687:
-----------------------------------

             Summary: Using @Transactional within a @DomainService Leads to a 
Missing Menu Entry
                 Key: CAUSEWAY-3687
                 URL: https://issues.apache.org/jira/browse/CAUSEWAY-3687
             Project: Causeway
          Issue Type: Bug
          Components: Viewer Wicket
    Affects Versions: 2.0.0-RC4
            Reporter: Jörg Rade


{code:java}
package com.kn.lx.domain;

import com.kn.lx.util.Constants;
import com.kn.lx.config.Properties;
import com.kn.lx.input.elastic.QueryResultItemTO;
import com.kn.lx.input.elastic.QueryService;
import com.kn.lx.input.elastic.pr.PrQuery;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.causeway.applib.annotation.Action;
import org.apache.causeway.applib.annotation.ActionLayout;
import org.apache.causeway.applib.annotation.DomainService;
import org.apache.causeway.applib.annotation.NatureOfService;
import org.apache.causeway.applib.annotation.Programmatic;
import org.apache.causeway.applib.annotation.SemanticsOf;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;
import javax.inject.Named;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Named("lx.Tasks")
@DomainService(nature = NatureOfService.VIEW)
@RequiredArgsConstructor(onConstructor_ = {@Inject})
public class Tasks {
    private final TaskRepository taskRepository;
    private final QueryService queryService;
    private final Executions executions;
    private final Properties properties;

    @Programmatic
    public Task create(String className) {
        final Task obj = new Task();
        obj.setQueryClassName(className);
        obj.setCronExpression(Constants.INSTANCE.getEVERY_FIVE_MINUTES());
        obj.setActive(true);
        taskRepository.saveAndFlush(obj);
        return obj;
    }

    @ActionLayout(sequence = "1")
    public List<Task> listAll() {
        return taskRepository.findAll();
    }

    public void init() {
        createIfAbsent(PrQuery.class.getCanonicalName());
    }

    @ActionLayout(sequence = "2")
    public void createIfAbsent(final String name) {
        final Task obj = taskRepository.findByQueryClassName(name);
        if (null == obj) {
            create(name);
        }
    }

    @Action(semantics = SemanticsOf.SAFE)
    @ActionLayout(sequence = "3", cssClassFa = "trash")
    public void delete(Task task) {
        taskRepository.delete(task);
    }

    List<QueryResultItemTO> executeQuery(PrQuery query) {
        final Integer chunkSize = 
properties.getInteger(Constants.INSTANCE.getELASTIC_QUERY_CHUNK_SIZE());
        query.setMaxNumberOfHits(chunkSize);
        String latestTimeStamp = 
properties.getString(Constants.INSTANCE.getEND_TIME_STAMP());
        if (latestTimeStamp.isEmpty()) {
            latestTimeStamp = 
properties.getString(Constants.INSTANCE.getSTART_TIME_STAMP());
        }
        return queryService.searchBy(query, latestTimeStamp);
    }

    @NonNull PrQuery createForClass(String queryClassName) {
        try {
            return (PrQuery) 
Class.forName(queryClassName).getDeclaredConstructor().newInstance();
        } catch (InstantiationException |
                 IllegalAccessException |
                 ClassNotFoundException |
                 InvocationTargetException |
                 NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    @Transactional
    public Task execute(Task argTask) {
        final Task task = update(argTask);
        if (task.isActive()) {
            final PrQuery query = createForClass(task.getQueryClassName());
            final List<QueryResultItemTO> queryResultList = executeQuery(query);
            final Execution e = executions.create(task, queryResultList);
            e.setEndedAt(LocalDateTime.now());
            e.setHits((long) queryResultList.size());
            task.getExecutionList().add(e);
            taskRepository.saveAndFlush(task);
            executions.sendMessagesFor(e);
            return task;
        }
        return null;
    }

    /**
     * It seems argTask is out of sync when it reaches this point.
     * Read it again.
     *
     * @param argTask Task to be synced
     * @return Task, synced with DB
     */
    private Task update(Task argTask) {
        final Optional<? extends Task> optionalTask = 
taskRepository.findById(argTask.getId());
        if (optionalTask.isPresent()) {
            return optionalTask.get();
        } else {
            throw new RuntimeException("Task not found");
        }
    }

}

{code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to