Deploying a Spring-Boot project using Maven and further importing it in other projects

Viewed 112

So currently, I have two projects, let's say Storefront and Dashboard, and both of these projects have the same POJO classes, Services, and some API Endpoints. For example, consider a class Student, we have this class in Storefront as well as in the Dashboard along with its service class. Further, in near future, we'll be implementing another project for clients, a Client Dashboard, that'll have almost 90% of the same resources.

So I thought, what if I create a maven project with all the libraries I need across all projects and import them as needed. This would reduce the redundancy and would also make other projects light weighted. I've previously used the in-project repository and Dropbox as a maven repository so it'll be a bit easier for me this time.

Now the problem is: I have the StudentRepository corresponding to the Student, which is further used with the '@Autowired' annotation right? As per my knowledge, everything will work when I run the '@SpringBootApplication' but as I previously mentioned, I'll be importing these packages, and doing so, the program will through a NullPointerException cause the instance of the StudentRepository will be null.

@SpringBootApplication
@EnableAutoConfiguration
@EntityScan
public class DemoApplication implements CommandLineRunner {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    StudentRepository repository;

    public static void main(String[] args) {
        SpringApplication.run(PaperTrueLibrariesApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // This will work
        logger.info("Inserting -> {}", repository.save(new Student("studentName", "primaryKey")));
    }
    
    // This won't
    public void addAStudent(String studentName, String primaryKey) {
        repository.save(new Student(studentName, primaryKey));
    }

}
public class Test {

    public static void main(String[] args) {
        // This will throw a NullPointerException
        new DemoApplication().addAStudent("yourNameProbably", "yourSocialSecurityNumber");
    }

}

So is there any other way to make this work? Any suggestions will be appreciated and thanks in advance.

2 Answers

There are two ways to achieve what you want -

First of all, add required jar that you have already created in your build file, say pom.xml for maven, in your current project.

If the class or code you are importing in different project is not a spring bean, then

In your configuration class, return it as a bean, using @Bean annotaion.

@Configuration
public class YourConfigurationClass {    

@Bean
SomeBean returnSomeBean() {
    return new SomeBean();
}

If your class is already a spring bean, you just need to ask spring to scan required package, as you already have that in your class path by adding dependency in maven.

@Configuration
@ComponentScan({"com.yourpackage.fromCommanCodeJar"})
public class YouApplicationConfigurationClass {....}

Assume that you have a library FooLibrary and main application FooApplication. The idea is importing FooLibrary in FooApplication.

Let's begin with FooLibrary. So mainly there are 2 important files. These are FooLibraryInterface and FooLibraryConfiguration. In this example I will not use FooLibraryInterface.

FooLibraryInterface is an interface that holds important methods that the client might need to override and FooLibraryConfiguration to scan and inject beans found in FooLibrary. So, here it follows

public interface FooLibraryInterface {
    public abstract Datasource configureDatabaseConnection();
}

FooLibraryConfiguration will be as the following:

@Configuration
@ComponentScan("package.to.scan")
public class FooLibraryConfiguration {
    @Bean
    public YourBean beanName() {
        return new YourBean();
    }
}

You can add all that you need in FooLibrary. Now our library is ready to be imported in FooApplication with the help of FooLibraryConfiguration

@SpringBootApplication
@Import(FooLibraryConfiguration.class) //this will import all the beans defined in the library
public class FooApplication {
    public static void main(String[] args) {
        SpringApplication.run(FooApplication.class, args);
    }
}

NOTE: If you have EntityManager managed classes(entity, repository), you should do an additional scan of the lib packages in the main application, since we don't need to have different EntityManager for a single application. Or you may scan all files together (leaving individual scans from @EnableJpaRepositories or em.setPackagesToScan("library.entities.package"); with @ComponentScan("base.library.package"))

@Configuration
@EnableJpaRepositories(basePackages = { "library.repository.package" })
@EnableTransactionManagement
public class PersistenceConfig {
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan("library.entities.package");

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }
    .....
}

UPDATE

Thank you @keshavram-kuduwa, you can reach the spring guides from https://spring.io/guides/gs/multi-module/#_create_the_library_project

Related