Приложение Spring полностью падает, когда я добавляю аннотацию @Transactional - PullRequest
0 голосов
/ 05 апреля 2020

У меня есть следующий метод, который вызывает два репозитория jpa для удаления некоторых кортежей. Очевидно, они должны быть аннотированы с помощью пружинной аннотации @Transactional.

@Override
@Transactional
public void deleteBasket(Long id)
{
    basketJpaRepository.deleteById(id);
    slaSpecificationJpaRepository.deleteByBasketId(id);
}

Когда я запускаю свои тесты, я получаю очень странную ошибку StackMap:

Caused by: java.lang.IllegalStateException: Unable to load cache item
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:79)
    at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:569)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:416)
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:58)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205)
    ... 113 more
Caused by: java.lang.VerifyError: Stack map does not match the one at exception handler 16
Exception Details:
  Location:
    com/scotiacapital/slopoke/persistence/service/BasketJpaService$$EnhancerBySpringCGLIB$$68de802a.<init>(Lcom/scotiacapital/slopoke/persistence/repository/BasketJpaRepository;Lcom/scotiacapital/slopoke/persistence/repository/SLASpecificationJpaRepository;Lcom/scotiacapital/slopoke/persistence/mapper/ClientConfigMapper;Lcom/scotiacapital/slopoke/persistence/service/IBasketIdGenerationService;Lcom/scotiacapital/slopoke/validation/BasketValidator;)V @16: athrow
  Reason:
    Current frame's flags are not assignable to stack map frame's.
  Current Frame:
    bci: @0
    flags: { flagThisUninit }
    locals: { uninitializedThis, 'com/scotiacapital/slopoke/persistence/repository/BasketJpaRepository', 'com/scotiacapital/slopoke/persistence/repository/SLASpecificationJpaRepository', 'com/scotiacapital/slopoke/persistence/mapper/ClientConfigMapper', 'com/scotiacapital/slopoke/persistence/service/IBasketIdGenerationService', 'com/scotiacapital/slopoke/validation/BasketValidator' }
    stack: { 'java/lang/RuntimeException' }
  Stackmap Frame:
    bci: @16
    flags: { }
    locals: { top, 'com/scotiacapital/slopoke/persistence/repository/BasketJpaRepository', 'com/scotiacapital/slopoke/persistence/repository/SLASpecificationJpaRepository', 'com/scotiacapital/slopoke/persistence/mapper/ClientConfigMapper', 'com/scotiacapital/slopoke/persistence/service/IBasketIdGenerationService', 'com/scotiacapital/slopoke/validation/BasketValidator' }
    stack: { 'java/lang/Throwable' }
  Bytecode:
    0000000: 2a59 2b2c 2d19 0419 05b7 0150 b800 38b1
    0000010: bfbb 004e 5a5f b700 51bf               
  Exception Handler Table:
    bci [0, 16] => handler: 16
    bci [0, 16] => handler: 16
    bci [0, 16] => handler: 17
  Stackmap Table:
    full_frame(@16,{Top,Object[#338],Object[#340],Object[#342],Object[#344],Object[#346]},{Object[#76]})
    same_locals_1_stack_item_frame(@17,Object[#76])

    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:416)
    at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:563)
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363)
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:582)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108)
    at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
    ... 120 more

Что делает "Причина: java .lang.VerifyError: Карта стека не совпадает с той, что у обработчика исключений 16 "означает? Как я могу это исправить?

РЕДАКТИРОВАТЬ:

Это мои зависимости:

dependencies {
    compile group: 'org.springframework', name: 'spring-core', version: '5.2.3.RELEASE'
    compile group: 'org.springframework.data', name: 'spring-data-elasticsearch', version: '3.2.3.RELEASE'
    implementation 'org.springframework.boot:spring-boot-starter-json'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    runtimeOnly 'org.springframework.boot:spring-boot-devtools'
    compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'com.h2database:h2'
    // lombok
    annotationProcessor('org.projectlombok:lombok')
    compileOnly('org.projectlombok:lombok')
    testAnnotationProcessor('org.projectlombok:lombok')
    testCompileOnly('org.projectlombok:lombok')

    // --- Test Dependencies ---
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit'
        exclude group: "com.vaadin.external.google", module: "android-json"
    }
    testCompile(group: 'org.mockito', name: 'mockito-junit-jupiter', version: '2.23.0')
    testCompile(group: 'org.hamcrest', name: 'hamcrest', version: '2.1')


    // JUnit Platform Support
    testCompile "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
    testCompile "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$jupiterVersion"

    // Mapstruct
    compile 'org.mapstruct:mapstruct:1.3.1.Final'
    annotationProcessor "org.mapstruct:mapstruct-processor:1.3.1.Final"

    // Swagger
    compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
    compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'

    // Kafka
    compile (group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.4.1.RELEASE') {
        exclude group: 'org.slf4j', module: 'slf4j-log4j12'
    }
    compile('io.confluent:kafka-streams-avro-serde:3.3.0') {
        exclude group: 'org.slf4j', module: 'slf4j-log4j12'

    }
//    compile group: 'io.confluent', name: 'kafka-avro-serializer', version: '5.4.0'
//    compile (group: 'io.confluent', name: 'kafka-schema-registry', version: '5.4.0') {
//            exclude group: 'org.slf4j', module: 'slf4j-log4j12'
//    }

    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.10.2'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.10.2'

    // Streaming
    compile group: 'org.apache.kafka', name: 'kafka-streams', version: '2.4.0'
    compile group: 'org.apache.kafka', name: 'kafka-clients', version: '2.4.0'
    compile group: 'org.springframework', name: 'spring-messaging', version: '5.2.3.RELEASE'

    //ES
    compile group: 'org.elasticsearch.client', name: 'elasticsearch-rest-client', version: '7.6.0'
    compile group: 'org.elasticsearch.client', name: 'elasticsearch-rest-high-level-client', version: '7.6.0'
    compile group: 'org.elasticsearch', name: 'elasticsearch', version: '7.6.0'
    compile group: 'org.elasticsearch.plugin', name: 'aggs-matrix-stats-client', version: '7.6.0'

    implementation 'com.cronutils:cron-utils:9.0.2'
}

Это мой класс обслуживания:

package com.scotiacapital.slopoke.persistence.service;

import com.scotiacapital.slopoke.exception.InvalidBasketException;
import com.scotiacapital.slopoke.domain.Basket;
import com.scotiacapital.slopoke.domain.OutboundTicket;
import com.scotiacapital.slopoke.persistence.repository.BasketJpaRepository;
import com.scotiacapital.slopoke.persistence.repository.SLASpecificationJpaRepository;
import com.scotiacapital.slopoke.persistence.dto.BasketJpaDto;
import com.scotiacapital.slopoke.persistence.dto.CompletenessSLASpecificationJpaDto;
import com.scotiacapital.slopoke.persistence.dto.ProcessingTimeSLASpecificationJpaDto;
import com.scotiacapital.slopoke.persistence.dto.TimelinessSLASpecificationJpaDto;
import com.scotiacapital.slopoke.persistence.mapper.ClientConfigMapper;
import com.scotiacapital.slopoke.sla.specs.CompletenessSLASpecification;
import com.scotiacapital.slopoke.sla.specs.ProcessingTimeSLASpecification;
import com.scotiacapital.slopoke.sla.specs.TimelinessSLASpecification;
import com.scotiacapital.slopoke.utils.StreamUtils;
import com.scotiacapital.slopoke.validation.BasketValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class BasketJpaService implements IBasketService
{
    private final BasketJpaRepository basketJpaRepository;
    private final SLASpecificationJpaRepository slaSpecificationJpaRepository;
    private final ClientConfigMapper clientConfigMapper;
    private final IBasketIdGenerationService basketIdGenerator;
    private final BasketValidator basketValidator;

    public BasketJpaService(BasketJpaRepository basketJpaRepository, SLASpecificationJpaRepository slaSpecificationJpaRepository, ClientConfigMapper clientConfigMapper, IBasketIdGenerationService basketIdGenerator, BasketValidator basketValidator)
    {
        this.basketJpaRepository = basketJpaRepository;
        this.slaSpecificationJpaRepository = slaSpecificationJpaRepository;
        this.clientConfigMapper = clientConfigMapper;
        this.basketIdGenerator = basketIdGenerator;
        this.basketValidator = basketValidator;
    }

    @Override
    public Map<String, List<Basket>> getSubSystemBasketMapping(String systemId)
    {
        List<BasketJpaDto> baskets = this.basketJpaRepository.getBasketsBySystemId(systemId);
        Map<String, List<Basket>> subSystemBasketMapping = new HashMap<>();
        for (BasketJpaDto basketJpaDto : baskets)
        {
            Basket basket = clientConfigMapper.mapFromPersistenceLevelToDomainLevel(basketJpaDto);
            Map<Class<? extends CompletenessSLASpecification>, ? extends List<? extends CompletenessSLASpecification>> slaMapping = getSLASpecMapping(basketJpaDto);
            putSLASpecsIntoBasket(basket, slaMapping);
            subSystemBasketMapping
                    .computeIfAbsent(basket.getSubSystemId(), k -> new ArrayList<>())
                    .add(basket);
        }
        return subSystemBasketMapping;

    }

    @SuppressWarnings("unchecked")
    private void putSLASpecsIntoBasket(Basket basket, Map<Class<? extends CompletenessSLASpecification>, ? extends List<? extends CompletenessSLASpecification>> slaJpaMapping)
    {
        basket.setCompletenessSLASpecifications((List<CompletenessSLASpecification>) slaJpaMapping.get(CompletenessSLASpecification.class));
        basket.setTimelinessSLASpecifications((List<TimelinessSLASpecification>) slaJpaMapping.get(TimelinessSLASpecification.class));
        basket.setProcessingTimeSLASpecifications((List<ProcessingTimeSLASpecification>) slaJpaMapping.get(ProcessingTimeSLASpecification.class));
    }

    private Map<Class<? extends CompletenessSLASpecification>, List<CompletenessSLASpecification>> getSLASpecMapping(BasketJpaDto b)
    {
        List<? extends CompletenessSLASpecificationJpaDto> slaSpecificationDtos = slaSpecificationJpaRepository.getAllByBasketId(b.getBasketId());
        Map<Class<? extends CompletenessSLASpecification>, List<CompletenessSLASpecification>> slaMapping = new HashMap<>();

        for (CompletenessSLASpecificationJpaDto jpaDto : slaSpecificationDtos)
        {
            if (jpaDto instanceof TimelinessSLASpecificationJpaDto)
            {
                TimelinessSLASpecification timelinessSLASpecification = clientConfigMapper.mapFromPersistenceLevelToDomainLevel((TimelinessSLASpecificationJpaDto) jpaDto);
                slaMapping.computeIfAbsent(TimelinessSLASpecification.class, k -> new ArrayList<>()).add(timelinessSLASpecification);
            } else if (jpaDto instanceof ProcessingTimeSLASpecificationJpaDto)
            {
                ProcessingTimeSLASpecification processingTimeSLASpecification = clientConfigMapper.mapFromPersistenceLevelToDomainLevel((ProcessingTimeSLASpecificationJpaDto) jpaDto);
                slaMapping.computeIfAbsent(ProcessingTimeSLASpecification.class, k -> new ArrayList<>()).add(processingTimeSLASpecification);
            } else
            {
                CompletenessSLASpecification completenessSLASpecification = clientConfigMapper.mapFromPersistenceLevelToDomainLevel(jpaDto);
                slaMapping.computeIfAbsent(CompletenessSLASpecification.class, k -> new ArrayList<>()).add(completenessSLASpecification);
            }
        }
        return slaMapping;
    }

    @Override
    public OutboundTicket<Long, Basket> acceptBasket(Basket basket) throws InvalidBasketException
    {
        OutboundTicket<Long, Basket> outboundTicket = new OutboundTicket<>();
        basketValidator.validate(basket);
        Long id = basketIdGenerator.generateId();
        Basket persistedBasket = persistBasket(basket, id);
        outboundTicket.setSuccess(persistedBasket, id);
        return outboundTicket;
    }

    @Override
    @Transactional
    public void deleteBasket(Long id)
    {
        basketJpaRepository.deleteById(id);
        slaSpecificationJpaRepository.deleteByBasketId(id);
    }


    private Basket persistBasket(Basket basket, Long id)
    {
        BasketJpaDto basketJpaDto = clientConfigMapper.mapFromDomainLevelToPersistenceLevel(basket);
        basketJpaDto.setBasketId(id);
        basketJpaRepository.save(basketJpaDto);
        List<CompletenessSLASpecificationJpaDto> completenessSLASpecificationJpaDtos = clientConfigMapper.mapFromDomainToPersistenceLevelCompleteness(basket.getCompletenessSLASpecifications());
        List<TimelinessSLASpecificationJpaDto> timelinessSLASpecificationJpaDtos = clientConfigMapper.mapFromDomainToPersistenceTimeliness(basket.getTimelinessSLASpecifications());
        List<ProcessingTimeSLASpecificationJpaDto> processingTimeSLASpecifications = clientConfigMapper.mapFromDomainToPersistenceLevelProcessingTime(basket.getProcessingTimeSLASpecifications());
        StreamUtils
                .fromListsNullSafe(completenessSLASpecificationJpaDtos, timelinessSLASpecificationJpaDtos, processingTimeSLASpecifications)
                .peek(item -> item.setBasketId(id))
                .forEach(slaSpecificationJpaRepository::save);
        return basket;
    }
}
...