Previously in Spring 2.7 we could inject a EntityManager Bean into a Service via Constructor

@Service
public class MyService {

    private final EntityManager entityManager;

    public MyService(EntityManager entityManager){
        this.entityManager = entityManager;
    }
}

In Spring-Boot this is not possible anymore. IntelliJ shows in Spring Boot 2.7, that the EntityManager Bean is injected from JpaBaseConfiguration's factory Method entityManagerFactory that returns a LocalContainerEntityManagerFactoryBean.

An alternative could be the @PersistenceContext annotation. But since I like to get the implementation from application context rather than container context, I would prefer the previous behavior.

Since I did not found anything in the migration guide or on the web I raise this issue here.

Comment From: bclozel

JpaBaseConfiguration is still exposing a LocalContainerEntityManagerFactoryBean, this didn't change in Spring Boot 3. Could you share a sample application that fails at injecting it?

Comment From: fabian-froehlich

Hi @bclozel , thanks for your quick response. I pusht an minimal example here: https://github.com/fabian-froehlich/bug_spring_entity_manager/

in the initial commit IntelliJ is able to link the bean to JpaBaseConfiguration. After chaning the dependency to Spring Boot 3, it does not work anymore.

Can you reproduce this behavior on your machine?

I would be interested in the mechanism behind this. How does spring know what to do with the factory? Usually I see a Bean definition that matches the Class or is an instance of it. But here it is a Factory that provides a lot of methods. How is the wanted Bean created from the Factory?

Comment From: bclozel

I've reduced the number of dependencies in the sample and added an h2 database. Then everything works when launching the project, the injection point works as expected.

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

When you said that this doesn't work in IntelliJ, I thought that running the project in IntelliJ would fail at startup with a missing bean. Now it sounds like you're pointing the fact that IntelliJ doesn't show a gutter icon or lets you know which bean is being injected? If this is a correct description, then you should create an issue in youtrack as this is out of our control.

Comment From: fabian-froehlich

You are absolutely right. I believed IntelliJ that there was an issue with the entity manager. I am also able to run the application with h2. My real project has some undergoing constructions in the migration process that lead me to believe that. Thank you clearing things up.

Comment From: bclozel

Thanks for letting us know! Don't hesitate to reach out if you're running into issues while upgrading, we can always improve the migration guide.