Springboot multimodule project

2019-08-23 04:21发布

问题:

I'm trying to get a clean springboot maven multimodule project. I'm using springboot 2.0.1.RELEASE

What I want to achieve is similar to this: SpringBootMultipleMavenModules

The problem I have is that I want to be able to inject my dependencies in any modules.

For example in this class: DBSeeder.java looks as follow:

private HotelRepository hotelRepository;

public DbSeeder(HotelRepository hotelRepository){
    this.hotelRepository = hotelRepository;
}
..

I would like to use instead:

@Autowired
private HotelRepository hotelRepository;

The Application class look as follow:

@SpringBootApplication
@EnableJpaRepositories(basePackages = {"rc"})
@EntityScan(basePackages = {"rc"})
@ComponentScan(basePackages = {"rc"})
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Any idea that could link me to the solution would be welcome.

回答1:

Looking at your code, you cannot Autowire a Hotel bean, because it's not registered properly.

https://github.com/IDCS1426/SpringBootMultipleMavenModules/blob/master/domain/src/main/java/rc/domain/Hotel.java#L10

You need to add @Component there to be able to inject it in https://github.com/IDCS1426/SpringBootMultipleMavenModules/blob/master/persistence/src/main/java/rc/persistence/DbSeeder.java#L21

Also, the project will never compile, as you're adding a non-existing module: https://github.com/IDCS1426/SpringBootMultipleMavenModules/blob/master/pom.xml#L14. You need to remove that :).

Having said all of that, it's very weird to me the way you're trying to inject an Entity like that, but that's not part of this question.

By doing that, the code compiles just fine.



回答2:

The working solution is available here. @Component was missing in the entity. Obviously, beans shouldn't been injected like done here, but instantiated (eg marriot = new Hotel("Marriot", 5, true);) and persisted through the save method (or saveAll for a Collection)

The injection of entities for the sole purpose of initialisation is wrong and won't work: The same instance will be reused for each Hotel.

@Autowired
private Hotel marriot, ibis, goldenTulip;

@Override
public void run(String... strings) throws Exception {

    marriot.setName("Marriot");
    marriot.setClassification(5);
    marriot.setOpen(true);

    ibis.setName("Ibis");
    ibis.setClassification(3);
    ibis.setOpen(false);

    goldenTulip.setName("Golden Tulip");
    goldenTulip.setClassification(4);
    goldenTulip.setOpen(true);

    List<Hotel> hotels = new ArrayList<>();
    hotels.add(marriot);
    hotels.add(ibis);
    hotels.add(goldenTulip);

    this.hotelRepository.saveAll(hotels);
}

Will result in one entity persisted, as all the 3 hotels are the same instance. As such, http://localhost:8080/hotels will return:

[{"id":1,"name":"Golden Tulip","classification":4,"open":true}]

While it with instantiation,

@Override
public void run(String... strings) throws Exception {
    marriot = new Hotel("Marriot", 5, true);
    ibis = new Hotel("Ibis", 3, false);
    goldenTulip = new Hotel("Golden Tulip", 4, true);

    List<Hotel> hotels = new ArrayList<>();
    hotels.add(marriot);
    hotels.add(ibis);
    hotels.add(goldenTulip);

    this.hotelRepository.saveAll(hotels);
}

it will return as it should the 3 entities:

[{"id":1,"name":"Marriot","classification":5,"open":true},{"id":2,"name":"Ibis","classification":3,"open":false},{"id":3,"name":"Golden Tulip","classification":4,"open":true}]

That's exactly what I wanted to see here, but forgot adding @Component to the Entity class. Must not do that!

EDIT: The reason for trying that was the use of a service layer:

public interface NoteService {
    List<Note> loadAll();
}
@Service
public class NoteServiceImpl implements NoteService {

  @Autowired
  private NoteRepository noteRepository;

  @Override
  public List<Note> loadAll() {
    return noteRepository.findAll();
  }
}

Which ended up failing at runtime, Note being not a managed bean.