Skip to content

Conversation

@werner77
Copy link

This fixes a NullPointerException we observe sometimes in our error reporting system.

Specifically because the calls to $$_hibernate_getEntityEntry() are duplicated and this resolves to a mutable field.

The NullPointerException stack trace we observe is:

java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.internal.AbstractEntityEntry.getPersister()" because "entityEntry" is null
    at org.hibernate.engine.internal.EntityEntryContext.getAssociatedManagedEntity(EntityEntryContext.java:168)
    at org.hibernate.engine.internal.EntityEntryContext.getEntityEntry(EntityEntryContext.java:231)
    at org.hibernate.engine.internal.StatefulPersistenceContext.getEntry(StatefulPersistenceContext.java:593)
    at org.hibernate.internal.SessionImpl.contains(SessionImpl.java:1603)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke(Method.java:580)
    ...

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.


@hibernate-github-bot
Copy link

hibernate-github-bot bot commented Nov 17, 2025

Thanks for your pull request!

This pull request does not follow the contribution rules. Could you have a look?

❌ All commit messages should start with a JIRA issue key matching pattern HHH-\d+
    ↳ Offending commits: [3ba92d7, 6027a68, 740c1a1, d51e27b, cde884d]

› This message was automatically generated.

Copy link
Member

@mbellade mbellade left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@werner77 note that various aspects of Hibernate's session are not thread safe, so if you're sharing the same instance between multiple threads you will run into more problems than just this NPE.

Not saying we won't accept this set of changes, reducing the number of times we invoke methods from the ManagedEntity interface is desirable anyway to avoid virtual call sites when using bytecode enhanced entities.

You seem to have based your changes on a very old version of the code though, please rebase on the current branch.

@gavinking
Copy link
Member

gavinking commented Nov 17, 2025

note that various aspects of Hibernate's session are not thread safe

Let's be much clearer about this: as is extensively documented, the session is not ever threadsafe, and you should never hit the session from more than one thread.

Not saying we won't accept this set of changes

I don't think we should accept it as-is.

Just changing stuff to return null or true when there's multithreaded access to the session is wrong.

Comment on lines 639 to 642
final EntityEntry entry = managedEntity.$$_hibernate_getEntityEntry();
if( entry == null ) {
return true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a condition that can only occur as a result of access to a session by concurrent threads, return true is not appropriate. It's better to throw.

Suggested change
final EntityEntry entry = managedEntity.$$_hibernate_getEntityEntry();
if( entry == null ) {
return true;
}
final EntityEntry entry = managedEntity.$$_hibernate_getEntityEntry();
if( entry == null ) {
throw new AssertionError("Probable multithreaded access to session");
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is old code, but the null case was already there and has nothing to do with concurrency. This is irrelevant anyway as in current main this method has been rewritten.

@werner77
Copy link
Author

werner77 commented Nov 17, 2025

I rebased the branch. Besides any threading issues I think the null safety can be addressed more properly as proposed. As far as I am aware though I am never sharing any sessions between multiple threads. I don't use Hibernate sessions directly, I am always interacting with them through an EntityManager proxy provided by Spring framework.

However, throwing an assertion error between two successive calls of the same property does not seem like the right place to guard against multi-threading? I guess that should be done at a more central place or guard all such invocations in a central manner?

@gavinking
Copy link
Member

However, throwing an assertion error between two successive calls of the same property does not seem like the right place to guard against multi-threading? I guess that should be done at a more central place or guard all such invocations in a central manner?

Hibernate itself cannot possibly to anything useful to guard against incorrect use of the session by your program or by Spring, because Hibernate is not in control of the thread pool, nor of allocation of work to the thread pool.

The best we can do is throw assertion errors if we detect something inconsistent in our internal state.

@werner77
Copy link
Author

werner77 commented Nov 17, 2025

I see the problematic pattern. I don't know if this is allowed by Hibernate or not:

schematically:

var entity = ... // some entity in this entityManager, part of the thread which starts an async task
asyncExectutor.execute((entityManager) -> {
    var attachedEntity = entity;
    if (!entityManager.contains(attachedEntity)) { // Nullpointer exception can be thrown on this line because of race condition
        // Load entity by primary key instead in this session
        attachedEntity = entityManager.find(...);
    }
}

I use this pattern to hand over entities to a different thread. The entityManager.contains is used as part of a generic utility method called attach where I ensure the entities are properly attached to the context.

@gavinking
Copy link
Member

I don't know if this is allowed by Hibernate or not:

Asynchronicity isn't completely disallowed. But you would have to ensure that any asynchronous process which accesses the session has exclusive access to the session from the point it is forked until the point it completes. After the asynchronous process completes, then some other process could in principle regain access to the session, but not before.

@werner77
Copy link
Author

werner77 commented Nov 18, 2025

Just for me to understand. So it is not allowed to hand an entity from one EntityManager to a different thread, having its own EntityManager and calling EntityManager.contains() in that other thread?

Because that is exactly the use case where the exception occurs.

The EntityManagers above (which wrap the Hibernate sessions) are distinct so NOT reused in different threads (they are injected by Spring framework via its thread safe proxy).

The problem arises because the managed entity itself has mutable state which is introspected before even the persistence context is compared in the contains() call.

@gavinking
Copy link
Member

So it is not allowed to hand an entity from one EntityManager to a different thread, having its own EntityManager and calling EntityManager.contains() in that other thread?

This is allowed. The contains() operation is defined to accept an instance that does not belong to the current persistence context.

Because that is exactly the use case where the exception occurs.

Very skeptical that this could possibly be true.

The problem arises because the managed entity itself has mutable state which is introspected before even the persistence context is compared in the contains() call.

WDYM by this? "Introspected" by what code written by who?

EntityManager.contains() certainly doesn't look at the state of the entity, all it does is check if there's an entry for that instance.

@werner77
Copy link
Author

werner77 commented Nov 18, 2025

Stack trace is as follows (according to my understanding):

  • SessionImpl.contains()
  • persistenceContext.getEntry()
  • entityEntryContext.getEntityEntry()
  • entityEntryContext.getAssociatedManagedEntity() (case where entity is a ManagedEntity)
  • asManagedEntity (only uses the entity itself, does not use entityEntryContext state)
  • managedEntity.$$_hibernate_getEntityEntry(); // Uses mutable state of the managedEntity: this is the problem. The entityEntry can be nulled by another thread / different entityEntryContext/persistenceContext.

Because there are two consecutive calls to the last method the result can change between those calls causing the issue.

private static class ManagedEntityImpl implements ManagedEntity {
		private final Object entityInstance;
		private EntityEntry entityEntry; // This is mutable!
		

Only later on this comparison is made:

entityEntry.getPersistenceContext() == persistenceContext

This would always return false for two different sessions. However, the NullPointerException can occur before that.

@gavinking
Copy link
Member

Well then that just sounds like a bug in the contains() method.

@werner77
Copy link
Author

werner77 commented Nov 18, 2025

Ok than either contains() should not eventually call entityEntryContext.getAssociatedManagedEntity() (which seems unlikely) or it should protect with locks, or the NullPointerException should be fixed as above without locking. I guess the latter is the cleanest. It won't have any negative side-effects because it does not change the semantics of the code, but only reduces some duplicated calls.

Am I missing anything?

@gavinking
Copy link
Member

I have no idea, because I have no way to reproduce the problem.

@gavinking
Copy link
Member

gavinking commented Nov 18, 2025

So you have proposed four changes. Two are perfectly unobjectionable, and should be done anyway, as @mbellade said earlier.

The other two look pretty suspicious and I don't see why they should be on the code path of the contains() method.

@werner77
Copy link
Author

I don't know how to create the proper unit test in the Hibernate source code, but I created a unit test in our code base:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = {TestApplication.class})
@ActiveProfiles("core")
public class HibernateCrashTest {

    @Autowired
    @Setter
    private DomainRepository domainRepository;

    @Autowired
    @Setter
    private TransactionExecutor transactionExecutor;

    @Autowired
    @Setter
    private TransactionSynchronizationService transactionSynchronizationService;

    @Autowired
    @Setter
    private EntityManager entityManager;

    @Test
    void testContainsThreadSafety() {

        transactionExecutor.withNewTransaction(() -> {
            var domain = new DomainEntity();
            domain.setName("Foo");
            domain.setCode(new DescriptiveCode("foo"));
            domainRepository.save(domain);
        });

        final int threadCount = 100;
        final int loopCount = 100;
        final List<Future<?>> futures = new ArrayList<>();

        try (ThreadPoolExecutor executor = new ThreadPoolExecutor(threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, new SynchronousQueue<>())) {
            for (int j = 0; j < loopCount; ++j) {
                transactionExecutor.withNewTransaction(() -> {
                    final var d = domainRepository.findByCode(new DescriptiveCode("foo")).orElseThrow();
                    for (int i = 0; i < threadCount; ++i) {
                        transactionSynchronizationService.performAfterCommit(() -> {
                            futures.add(executor.submit(() -> {
                                if (entityManager.contains(d)) {
                                    fail("Entity manager should not contain domain entity");
                                }
                            }));
                        });
                    }
                });
                futures.forEach(future -> { try { future.get(); } catch (Exception e) { fail(e); }});
                futures.clear();
            }
        }
    }
}

This test crashes with the NullPointerException as described:

org.opentest4j.AssertionFailedError
	at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:46)
	at org.junit.jupiter.api.Assertions.fail(Assertions.java:161)
	at org.beatkit.core.service.message.HibernateCrashTest.lambda$testContainsThreadSafety$4(HibernateCrashTest.java:80)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at org.beatkit.core.service.message.HibernateCrashTest.testContainsThreadSafety(HibernateCrashTest.java:80)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.internal.AbstractEntityEntry.getPersister()" because "entityEntry" is null
	at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
	... 6 more
Caused by: java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.internal.AbstractEntityEntry.getPersister()" because "entityEntry" is null
	at org.hibernate.engine.internal.EntityEntryContext.getAssociatedManagedEntity(EntityEntryContext.java:168)
	at org.hibernate.engine.internal.EntityEntryContext.getEntityEntry(EntityEntryContext.java:231)
	at org.hibernate.engine.internal.StatefulPersistenceContext.getEntry(StatefulPersistenceContext.java:593)
	at org.hibernate.internal.SessionImpl.contains(SessionImpl.java:1607)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:364)
	at jdk.proxy1/jdk.proxy1.$Proxy163.contains(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:320)
	at jdk.proxy1/jdk.proxy1.$Proxy163.contains(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
	at org.beatkit.persistence.fix.EntityManagerContainsFixAspect.safeContains(EntityManagerContainsFixAspect.java:18)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:642)
	at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:632)
	at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:173)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
	at jdk.proxy1/jdk.proxy1.$Proxy164.contains(Unknown Source)
	at org.beatkit.core.service.message.HibernateCrashTest.lambda$testContainsThreadSafety$1(HibernateCrashTest.java:73)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:317)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at --- Async.Stack.Trace --- (captured by IntelliJ IDEA debugger)
	at java.base/java.util.concurrent.FutureTask.<init>(FutureTask.java:151)
	at java.base/java.util.concurrent.AbstractExecutorService.newTaskFor(AbstractExecutorService.java:98)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:122)
	at org.beatkit.core.service.message.HibernateCrashTest.lambda$testContainsThreadSafety$2(HibernateCrashTest.java:72)
	at org.beatkit.service.SpringTransactionSynchronizationService$1.afterCommit(SpringTransactionSynchronizationService.java:23)
	at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:165)
	at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerAfterCommit(TransactionSynchronizationUtils.java:153)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCommit(AbstractPlatformTransactionManager.java:1006)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:836)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:758)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:698)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:416)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:727)
	at org.beatkit.service.TransactionExecutorImpl$$SpringCGLIB$$0.withNewTransaction(<generated>)
	at org.beatkit.core.service.message.HibernateCrashTest.testContainsThreadSafety(HibernateCrashTest.java:68)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:767)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$8(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:156)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:146)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:144)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:100)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:160)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:146)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:144)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:100)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:160)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:146)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:144)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:100)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:198)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:169)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:93)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:58)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:141)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:57)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:103)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:85)
	at org.junit.platform.launcher.core.DelegatingLauncher.execute(DelegatingLauncher.java:47)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:63)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:66)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

@werner77
Copy link
Author

I removed the two changes which were not necessary/problematic

Copy link
Member

@mbellade mbellade left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, one minor nitpick but other than that this is fine.

@mbellade
Copy link
Member

Thanks @werner77, please squash everything to a single commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants