├── README.adoc ├── application ├── pom.xml └── src │ └── main │ ├── java │ └── sample │ │ └── multimodule │ │ ├── SampleWebJspApplication.java │ │ └── web │ │ └── WelcomeController.java │ └── resources │ ├── application.properties │ └── templates │ └── welcome │ └── show.html ├── configuration └── settings.xml ├── model ├── pom.xml └── src │ └── main │ └── java │ └── sample │ └── multimodule │ └── domain │ └── entity │ └── Account.java ├── pom.xml ├── repository ├── pom.xml └── src │ └── main │ └── java │ └── sample │ └── multimodule │ └── repository │ └── AccountRepository.java ├── service-api ├── pom.xml └── src │ └── main │ └── java │ └── sample │ └── multimodule │ └── service │ └── api │ ├── AccountNotFoundException.java │ └── AccountService.java └── service-impl ├── pom.xml └── src └── main └── java └── sample └── multimodule └── service └── impl └── AccountServiceImpl.java /README.adoc: -------------------------------------------------------------------------------- 1 | = Spring Boot Multimodule project example 2 | 3 | Proofs of concept that shows how to generate Spring Boot multimodule 4 | applications. 5 | 6 | === Description 7 | 8 | This project is an Spring Boot multimodule application with the following 9 | structure. 10 | 11 | [source] 12 | ---- 13 | . 14 | ├── application 15 | │   ├── pom.xml 16 | │   └── src 17 | │   └── main 18 | │   ├── java 19 | │   │   └── sample 20 | │   │   └── multimodule 21 | │   │   ├── SampleWebJspApplication.java 22 | │   │   └── web 23 | │   │   └── WelcomeController.java 24 | │   └── resources 25 | │   ├── application.properties 26 | │   └── templates 27 | │   └── welcome 28 | │   └── show.html 29 | ├── model 30 | │   ├── pom.xml 31 | │   └── src 32 | │   └── main 33 | │   └── java 34 | │   └── sample 35 | │   └── multimodule 36 | │   └── domain 37 | │   └── entity 38 | │   └── Account.java 39 | ├── pom.xml 40 | ├── repository 41 | │   ├── pom.xml 42 | │   └── src 43 | │   └── main 44 | │   └── java 45 | │   └── sample 46 | │   └── multimodule 47 | │   └── repository 48 | │   └── AccountRepository.java 49 | ├── service-api 50 | │   ├── pom.xml 51 | │   └── src 52 | │   └── main 53 | │   └── java 54 | │   └── sample 55 | │   └── multimodule 56 | │   └── service 57 | │   └── api 58 | │   ├── AccountNotFoundException.java 59 | │   └── AccountService.java 60 | └── service-impl 61 | ├── pom.xml 62 | └── src 63 | └── main 64 | └── java 65 | └── sample 66 | └── multimodule 67 | └── service 68 | └── impl 69 | └── AccountServiceImpl.java 70 | 71 | ---- 72 | 73 | Every module match with some application layer (service layer, repository layer, web layer, model, etc..). 74 | 75 | ==== Parent - Pom Aggregator 76 | 77 | This module is a maven aggregator that contains all application modules. Also, include all 78 | common dependencies needed by more than one module. Dependencies are defined without version because 79 | this project has defined Spring IO Platform as parent. 80 | 81 | ==== Project Module - Model 82 | 83 | Module that contains all Entities and Visual Objects to be used in the project. It doesn't have any dependencies. 84 | 85 | ==== Project Module - Repository 86 | 87 | Module that contains all repositories to be used in the project. Depends of Model Module. 88 | 89 | ==== Project Module - Service API 90 | 91 | Module that contains API of all project services. Depends of Model Module. 92 | 93 | ==== Project Module - Service Implementation 94 | 95 | Module that contains services implementation defined on Service API module. Depends of Repository Module and Service API Module. 96 | 97 | ==== Project Module - Application 98 | 99 | This is the main module of the project. It contains Application.java class, 100 | that contains main method, necessary to run Spring Boot applications. It 101 | contains all necessary application configuration properties. It contains all 102 | web controllers, views and web resources. It include Model Module and Service 103 | Implementation module as dependency that contains Model Module, Repository 104 | Module and Service API module. 105 | 106 | === Test 107 | 108 | Follow these instructions to execute application using embedded tomcat server: 109 | 110 | * Generate project distribution using *mvn clean install* command on Parent 111 | module. 112 | * Execute *mvn spring-boot:run* command on Application module (contains .war) 113 | * Open browser on *http://localhost:8080* 114 | * Test *http://localhost:8080/*. You should see account information with "23" 115 | number. 116 | 117 | -------------------------------------------------------------------------------- /application/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | sample.multimodule 6 | sample.multimodule 7 | 0.0.1-SNAPSHOT 8 | 9 | sample.multimodule.application 10 | jar 11 | Project Module - Application 12 | This is the main module of the project. It contains Application.java class, that contains main method, 13 | necessary to run Spring Boot applications. It contains all necessary application configuration properties. 14 | It contains all web controllers, views and web resources. It include Service Implementation module 15 | as dependency that contains Model Module, Repository Module and Service Api Module. 16 | 17 | 18 | 19 | 20 | 21 | sample.multimodule 22 | sample.multimodule.service.impl 23 | ${project.version} 24 | 25 | 26 | 27 | 28 | org.apache.tomcat.embed 29 | tomcat-embed-jasper 30 | provided 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-web 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-thymeleaf 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /application/src/main/java/sample/multimodule/SampleWebJspApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package sample.multimodule; 18 | 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.boot.orm.jpa.EntityScan; 22 | 23 | @SpringBootApplication 24 | public class SampleWebJspApplication { 25 | 26 | public static void main(String[] args) throws Exception { 27 | SpringApplication.run(SampleWebJspApplication.class, args); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /application/src/main/java/sample/multimodule/web/WelcomeController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package sample.multimodule.web; 18 | 19 | import java.util.Date; 20 | import java.util.Map; 21 | 22 | 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.beans.factory.annotation.Value; 25 | import org.springframework.stereotype.Controller; 26 | import org.springframework.web.bind.annotation.RequestMapping; 27 | 28 | import sample.multimodule.domain.entity.Account; 29 | import sample.multimodule.service.api.AccountService; 30 | 31 | @Controller 32 | public class WelcomeController { 33 | 34 | @Value("${application.message:Hello World}") 35 | private String message = "Hello World"; 36 | 37 | @Autowired 38 | protected AccountService accountService; 39 | 40 | @RequestMapping("/") 41 | public String welcome(Map model) { 42 | // Trying to obtain 23 account 43 | Account account = accountService.findOne("23"); 44 | if(account == null){ 45 | // If there's some problem creating account, return show view with error status 46 | model.put("message", "Error getting account!"); 47 | model.put("account", ""); 48 | return "welcome/show"; 49 | } 50 | 51 | // Return show view with 23 account info 52 | String accountInfo = "Your account number is ".concat(account.getNumber()); 53 | model.put("message", this.message); 54 | model.put("account", accountInfo); 55 | return "welcome/show"; 56 | } 57 | 58 | @RequestMapping("foo") 59 | public String foo(Map model) { 60 | throw new RuntimeException("Foo"); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Application messages 2 | application.message = Hello User! 3 | dummy.type = type-inside-the-war 4 | 5 | # Spring Thymeleaf config 6 | spring.thymeleaf.cache = false 7 | 8 | -------------------------------------------------------------------------------- /application/src/main/resources/templates/welcome/show.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Spring Boot Multimodule 5 | 6 | 7 | 8 |
9 | Message: 10 | 11 |
12 |
13 | Your account: 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /configuration/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 46 | 49 | 55 | 56 | 64 | 65 | 72 | 73 | 78 | 79 | 83 | 84 | 85 | 90 | 91 | 105 | 106 | 107 | 111 | 112 | 125 | 126 | 133 | 134 | 135 | 146 | 147 | 159 | 160 | 161 | 182 | 183 | 212 | 213 | 247 | 248 | 249 | 257 | 258 | -------------------------------------------------------------------------------- /model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | sample.multimodule 6 | sample.multimodule 7 | 0.0.1-SNAPSHOT 8 | 9 | sample.multimodule.model 10 | jar 11 | Project Module - Model 12 | Module that contains all Entities and Visual Objects to be used in the project. It doesn't have any dependencies. 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /model/src/main/java/sample/multimodule/domain/entity/Account.java: -------------------------------------------------------------------------------- 1 | package sample.multimodule.domain.entity; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.Id; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | 8 | 9 | @Entity 10 | public class Account { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.AUTO) 14 | private Long id; 15 | 16 | private String number; 17 | 18 | private String type; 19 | 20 | private String creditCardNumber; 21 | 22 | /** 23 | * Create an empty account. 24 | */ 25 | public Account() { 26 | 27 | } 28 | 29 | /** 30 | * Create a new account. 31 | * 32 | * @param number 33 | * the account number 34 | * @param id 35 | * the account id 36 | */ 37 | public Account(Long id, String number) { 38 | this.number = number; 39 | this.id = id; 40 | } 41 | 42 | public Long getId() { 43 | return id; 44 | } 45 | 46 | public void setId(Long id) { 47 | this.id = id; 48 | } 49 | 50 | public String getNumber() { 51 | return number; 52 | } 53 | 54 | public void setNumber(String number) { 55 | this.number = number; 56 | } 57 | 58 | public String getType() { 59 | return type; 60 | } 61 | 62 | public void setType(String type) { 63 | this.type = type; 64 | } 65 | 66 | public String getCreditCardNumber() { 67 | return creditCardNumber; 68 | } 69 | 70 | public void setCreditCardNumber(String creditCardNumber) { 71 | this.creditCardNumber = creditCardNumber; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 6 | 7 | io.spring.platform 8 | platform-bom 9 | 2.0.1.RELEASE 10 | 11 | sample.multimodule 12 | sample.multimodule 13 | 0.0.1-SNAPSHOT 14 | pom 15 | Parent - Pom Aggregator 16 | This pom is a maven aggregator that contains all application modules. Also, include all 17 | common dependencies needed by more than one module. Dependencies are defined without version because 18 | this project has defined Spring IO Platform as parent. 19 | 20 | 21 | 1.6 22 | 23 | 24 | 25 | model 26 | repository 27 | service-api 28 | service-impl 29 | application 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-data-jpa 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-test 46 | test 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /repository/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | sample.multimodule 6 | sample.multimodule 7 | 0.0.1-SNAPSHOT 8 | 9 | sample.multimodule.repository 10 | jar 11 | Project Module - Repository 12 | Module that contains all repositories to be used in the project. Depends of Model Module. 13 | 14 | 15 | 16 | 17 | sample.multimodule 18 | sample.multimodule.model 19 | ${project.version} 20 | 21 | 22 | 23 | 24 | org.hsqldb 25 | hsqldb 26 | runtime 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /repository/src/main/java/sample/multimodule/repository/AccountRepository.java: -------------------------------------------------------------------------------- 1 | package sample.multimodule.repository; 2 | 3 | import org.springframework.data.domain.*; 4 | import org.springframework.data.repository.*; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import sample.multimodule.domain.entity.Account; 8 | 9 | @Repository 10 | public interface AccountRepository extends CrudRepository { 11 | 12 | Account findByNumber(String number); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /service-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | sample.multimodule 6 | sample.multimodule 7 | 0.0.1-SNAPSHOT 8 | 9 | sample.multimodule.service.api 10 | jar 11 | Project Module - Service API 12 | Module that contains API of all project services. Depends of Model Module. 13 | 14 | 15 | 16 | 17 | 18 | sample.multimodule 19 | sample.multimodule.model 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /service-api/src/main/java/sample/multimodule/service/api/AccountNotFoundException.java: -------------------------------------------------------------------------------- 1 | package sample.multimodule.service.api; 2 | 3 | public class AccountNotFoundException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = -3891534644498426670L; 6 | 7 | public AccountNotFoundException(String accountId) { 8 | super("No such account with id: " + accountId); 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /service-api/src/main/java/sample/multimodule/service/api/AccountService.java: -------------------------------------------------------------------------------- 1 | package sample.multimodule.service.api; 2 | 3 | import java.util.List; 4 | import sample.multimodule.domain.entity.Account; 5 | 6 | public interface AccountService { 7 | 8 | /** 9 | * Finds the account with the provided account number. 10 | * 11 | * @param number The account number 12 | * @return The account 13 | * @throws AccountNotFoundException If no such account exists. 14 | */ 15 | Account findOne(String number) throws AccountNotFoundException; 16 | 17 | /** 18 | * Creates a new account. 19 | * 20 | * @param number 21 | * @return created account 22 | */ 23 | Account createAccountByNumber(String number); 24 | } 25 | -------------------------------------------------------------------------------- /service-impl/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | sample.multimodule 6 | sample.multimodule 7 | 0.0.1-SNAPSHOT 8 | 9 | sample.multimodule.service.impl 10 | jar 11 | Project Module - Service Implementation 12 | Module that contains services implementation defined on Service API module. Depends of Repository Module and 13 | Service API Module. 14 | 15 | 16 | 17 | 18 | 19 | sample.multimodule 20 | sample.multimodule.repository 21 | ${project.version} 22 | 23 | 24 | sample.multimodule 25 | sample.multimodule.service.api 26 | ${project.version} 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /service-impl/src/main/java/sample/multimodule/service/impl/AccountServiceImpl.java: -------------------------------------------------------------------------------- 1 | package sample.multimodule.service.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import sample.multimodule.domain.entity.Account; 11 | import sample.multimodule.repository.AccountRepository; 12 | import sample.multimodule.service.api.AccountService; 13 | import sample.multimodule.service.api.AccountNotFoundException; 14 | 15 | @Service 16 | public class AccountServiceImpl implements AccountService { 17 | 18 | @Value("${dummy.type}") 19 | private String dummyType; 20 | 21 | @Autowired 22 | private AccountRepository accountRepository; 23 | 24 | /** 25 | * {@inheritDoc} 26 | *

27 | * Dummy method for testing purposes. 28 | * 29 | * @param number The account number. Set 0000 to get an {@link AccountNotFoundException} 30 | */ 31 | @Override 32 | public Account findOne(String number) throws AccountNotFoundException { 33 | if(number.equals("0000")) { 34 | throw new AccountNotFoundException("0000"); 35 | } 36 | 37 | Account account = accountRepository.findByNumber(number); 38 | if(account == null){ 39 | account = createAccountByNumber(number); 40 | } 41 | 42 | return account; 43 | } 44 | 45 | @Override 46 | public Account createAccountByNumber(String number) { 47 | Account account = new Account(); 48 | account.setNumber(number); 49 | return accountRepository.save(account); 50 | } 51 | 52 | public String getDummyType() { 53 | return dummyType; 54 | } 55 | 56 | public void setDummyType(String dummyType) { 57 | this.dummyType = dummyType; 58 | } 59 | 60 | } 61 | --------------------------------------------------------------------------------