├── .gitignore ├── README.md ├── api ├── pom.xml └── src │ └── main │ ├── java │ ├── com │ │ └── lohika │ │ │ └── morning │ │ │ └── java9modules │ │ │ └── api │ │ │ ├── ApplicationConfiguration.java │ │ │ └── controller │ │ │ └── MovieController.java │ └── module-info.java │ └── resources │ └── application.properties ├── pom.xml └── service ├── pom.xml └── src ├── main ├── java │ ├── com │ │ └── lohika │ │ │ └── morning │ │ │ └── java9modules │ │ │ └── service │ │ │ ├── configuration │ │ │ └── ServiceConfiguration.java │ │ │ ├── domain │ │ │ └── Movie.java │ │ │ ├── repository │ │ │ ├── MovieRepository.java │ │ │ └── MovieRepositoryImpl.java │ │ │ └── service │ │ │ └── MovieService.java │ └── module-info.java └── resources │ └── service.properties └── test └── resources ├── application-test.properties ├── logback-test.xml └── spark-test.properties /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .classpath 3 | .project 4 | .settings/ 5 | 6 | # Intellij 7 | .idea/ 8 | *.iml 9 | *.iws 10 | # Mac 11 | .DS_Store 12 | 13 | # Maven 14 | log/ 15 | target/ 16 | 17 | # Gradle 18 | build/ 19 | .gradle/ 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # java9-springboot 2 | Demo application to evaluate Java 9 modules integration with Spring Boot. 3 | 4 | There are 2 modules: 5 | * api 6 | * service 7 | 8 | Where api is dependent on some packages from service. 9 | The main idea was to create valid module-info.java classes to define valid exports, but, which is more important even, to open valid packages to Spring to be used via reflection. 10 | 11 | The application cannot be started via Intellij IDEA. 12 | 13 | In order to run: 14 | * mvn clean install 15 | * java -jar api/target/api-1.0-SNAPSHOT-exec.jar 16 | -------------------------------------------------------------------------------- /api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.lohika.morning.java9modules 7 | java-9-modules 8 | 1.0-SNAPSHOT 9 | 10 | 11 | api 12 | 4.0.0 13 | 14 | 15 | 16 | com.lohika.morning.java9modules 17 | service 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-jetty 28 | 29 | 30 | -------------------------------------------------------------------------------- /api/src/main/java/com/lohika/morning/java9modules/api/ApplicationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.api; 2 | 3 | import com.lohika.morning.java9modules.service.configuration.ServiceConfiguration; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.ComponentScan; 7 | import org.springframework.context.annotation.Import; 8 | 9 | @SpringBootApplication 10 | @ComponentScan(value = "com.lohika.morning.java9modules.api.*") 11 | @Import(ServiceConfiguration.class) 12 | public class ApplicationConfiguration { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(ApplicationConfiguration.class, args); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /api/src/main/java/com/lohika/morning/java9modules/api/controller/MovieController.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.api.controller; 2 | 3 | import com.lohika.morning.java9modules.service.domain.Movie; 4 | import com.lohika.morning.java9modules.service.service.MovieService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.List; 12 | 13 | @RestController 14 | @RequestMapping("/movies") 15 | public class MovieController { 16 | 17 | @Autowired 18 | private MovieService movieService; 19 | 20 | @GetMapping 21 | public List all() { 22 | return this.movieService.allMovies(); 23 | } 24 | 25 | @GetMapping("/{id}") 26 | public Movie byId(@PathVariable String id) { 27 | return this.movieService.movieById(id).orElse(new Movie("Default title", "Default Genre")); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /api/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module com.lohika.morning.java9modules.api { 2 | 3 | requires java.sql; 4 | requires java.xml.ws.annotation; 5 | 6 | requires spring.core; 7 | requires spring.beans; 8 | requires spring.context; 9 | requires spring.aop; 10 | requires spring.web; 11 | requires spring.expression; 12 | 13 | requires spring.boot; 14 | requires spring.boot.autoconfigure; 15 | 16 | requires com.lohika.morning.java9modules.service; 17 | 18 | exports com.lohika.morning.java9modules.api; 19 | exports com.lohika.morning.java9modules.api.controller; 20 | 21 | opens com.lohika.morning.java9modules.api; 22 | opens com.lohika.morning.java9modules.api.controller; 23 | } -------------------------------------------------------------------------------- /api/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # In order not to overlap with other applications. 2 | server.port=9090 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.lohika.morning.java9modules 8 | java-9-modules 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | 13 | api 14 | service 15 | 16 | 17 | 18 | 2.0.0.BUILD-SNAPSHOT 19 | 5.0.0.BUILD-SNAPSHOT 20 | UTF-8 21 | com.lohika.morning.java9modules.api.ApplicationConfiguration 22 | 23 | 24 | 25 | 26 | spring-snapshots 27 | Spring Snapshots 28 | https://repo.spring.io/snapshot 29 | 30 | true 31 | 32 | 33 | 34 | spring-milestones 35 | Spring Milestones 36 | https://repo.spring.io/milestone 37 | 38 | false 39 | 40 | 41 | 42 | 43 | 44 | 45 | spring-snapshots 46 | Spring Snapshots 47 | https://repo.spring.io/snapshot 48 | 49 | true 50 | 51 | 52 | 53 | spring-milestones 54 | Spring Milestones 55 | https://repo.spring.io/milestone 56 | 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | com.lohika.morning.java9modules 66 | api 67 | ${project.version} 68 | 69 | 70 | 71 | com.lohika.morning.java9modules 72 | service 73 | ${project.version} 74 | 75 | 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-dependencies 80 | ${spring-boot.version} 81 | pom 82 | import 83 | 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-starter-web 88 | ${spring-boot.version} 89 | 90 | 91 | 92 | org.springframework.boot 93 | spring-boot-starter-jetty 94 | ${spring-boot.version} 95 | 96 | 97 | 98 | org.springframework.boot 99 | spring-boot-starter-data-mongodb 100 | ${spring-boot.version} 101 | 102 | 103 | 104 | org.springframework 105 | spring-context 106 | ${spring.version} 107 | 108 | 109 | 110 | org.springframework 111 | spring-beans 112 | ${spring.version} 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | org.springframework.boot 121 | spring-boot-maven-plugin 122 | 2.0.0.BUILD-SNAPSHOT 123 | 124 | 125 | 126 | repackage 127 | 128 | 129 | exec 130 | ${start-class} 131 | 132 | 133 | 134 | 135 | 136 | org.apache.maven.plugins 137 | maven-compiler-plugin 138 | 3.6.1 139 | 140 | 1.9 141 | 1.9 142 | true 143 | true 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.lohika.morning.java9modules 7 | java-9-modules 8 | 1.0-SNAPSHOT 9 | 10 | 11 | service 12 | 4.0.0 13 | 14 | 15 | 16 | org.springframework 17 | spring-beans 18 | 19 | 20 | 21 | org.springframework 22 | spring-context 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /service/src/main/java/com/lohika/morning/java9modules/service/configuration/ServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.service.configuration; 2 | 3 | import org.springframework.context.annotation.ComponentScan; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @ComponentScan("com.lohika.morning.java9modules.service.*") 8 | //@EnableMongoRepositories("com.lohika.morning.java9modules.service.repository") 9 | public class ServiceConfiguration { 10 | } 11 | -------------------------------------------------------------------------------- /service/src/main/java/com/lohika/morning/java9modules/service/domain/Movie.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.service.domain; 2 | 3 | //@Document(collection = "movies") 4 | public class Movie { 5 | 6 | // @Id 7 | private String id; 8 | 9 | private String title; 10 | 11 | private String genre; 12 | 13 | public Movie() { 14 | } 15 | 16 | public Movie(String title, String genre) { 17 | this.title = title; 18 | this.genre = genre; 19 | } 20 | 21 | public String getId() { 22 | return id; 23 | } 24 | 25 | public void setId(String id) { 26 | this.id = id; 27 | } 28 | 29 | public String getTitle() { 30 | return title; 31 | } 32 | 33 | public void setTitle(String title) { 34 | this.title = title; 35 | } 36 | 37 | public String getGenre() { 38 | return genre; 39 | } 40 | 41 | public void setGenre(String genre) { 42 | this.genre = genre; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /service/src/main/java/com/lohika/morning/java9modules/service/repository/MovieRepository.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.service.repository; 2 | 3 | import com.lohika.morning.java9modules.service.domain.Movie; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | public interface MovieRepository { 9 | 10 | List findAll(); 11 | 12 | Optional findOne(String id); 13 | 14 | Optional findByTitle(String title); 15 | 16 | List findByGenre(String genre); 17 | 18 | void deleteAll(); 19 | 20 | void save(Movie movie); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /service/src/main/java/com/lohika/morning/java9modules/service/repository/MovieRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.service.repository; 2 | 3 | import com.lohika.morning.java9modules.service.domain.Movie; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.Optional; 9 | 10 | @Component 11 | public class MovieRepositoryImpl implements MovieRepository { 12 | 13 | List movies = fillMovies(); 14 | 15 | private List fillMovies() { 16 | return new ArrayList<>(); 17 | } 18 | 19 | @Override 20 | public List findAll() { 21 | return movies; 22 | } 23 | 24 | @Override 25 | public Optional findOne(String id) { 26 | return Optional.of(movies.get(0)); 27 | } 28 | 29 | @Override 30 | public Optional findByTitle(String title) { 31 | return Optional.of(movies.get(0)); 32 | } 33 | 34 | @Override 35 | public List findByGenre(String genre) { 36 | return movies; 37 | } 38 | 39 | @Override 40 | public void deleteAll() { 41 | 42 | } 43 | 44 | @Override 45 | public void save(Movie movie) { 46 | movies.add(movie); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /service/src/main/java/com/lohika/morning/java9modules/service/service/MovieService.java: -------------------------------------------------------------------------------- 1 | package com.lohika.morning.java9modules.service.service; 2 | 3 | import com.lohika.morning.java9modules.service.domain.Movie; 4 | import com.lohika.morning.java9modules.service.repository.MovieRepository; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.PostConstruct; 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | import java.util.Optional; 11 | import java.util.Random; 12 | import java.util.stream.Stream; 13 | 14 | @Service 15 | public class MovieService { 16 | 17 | @Resource 18 | private MovieRepository movieRepository; 19 | 20 | public List allMovies() { 21 | return this.movieRepository.findAll(); 22 | } 23 | 24 | public Optional movieById(String id) { 25 | return this.movieRepository.findOne(id); 26 | } 27 | 28 | public Optional movieByTitle(String title) { 29 | return this.movieRepository.findByTitle(title); 30 | } 31 | 32 | public List moviesByGenre(String genre) { 33 | return this.movieRepository.findByGenre(genre); 34 | } 35 | 36 | @PostConstruct 37 | public void setUpMovies() { 38 | movieRepository.deleteAll(); 39 | Stream.of("Terminator", "Matrix", "Titanic") 40 | .map(title -> new Movie(title, randomGenre())) 41 | .forEach(movie -> movieRepository.save(movie)); 42 | } 43 | 44 | private String randomGenre() { 45 | String[] genres = "Comedy, Drama, Documentary, Horror, Family".split(", "); 46 | return genres[new Random().nextInt(genres.length)]; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /service/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module com.lohika.morning.java9modules.service { 2 | 3 | requires java.xml.ws.annotation; 4 | requires spring.beans; 5 | requires spring.context; 6 | 7 | exports com.lohika.morning.java9modules.service.service to com.lohika.morning.java9modules.api; 8 | exports com.lohika.morning.java9modules.service.domain to com.lohika.morning.java9modules.api; 9 | exports com.lohika.morning.java9modules.service.configuration to com.lohika.morning.java9modules.api; 10 | 11 | opens com.lohika.morning.java9modules.service.service; 12 | opens com.lohika.morning.java9modules.service.configuration; 13 | opens com.lohika.morning.java9modules.service.repository; 14 | } -------------------------------------------------------------------------------- /service/src/main/resources/service.properties: -------------------------------------------------------------------------------- 1 | #mongodb 2 | spring.data.mongodb.host=localhost 3 | spring.data.mongodb.port=27017 4 | spring.data.mongodb.database=java9modules 5 | -------------------------------------------------------------------------------- /service/src/test/resources/application-test.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tmatyashovsky/java9-springboot/fab2d62f971d59ca860dd031ccac92c2939b445c/service/src/test/resources/application-test.properties -------------------------------------------------------------------------------- /service/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /service/src/test/resources/spark-test.properties: -------------------------------------------------------------------------------- 1 | spark.master=local[2] 2 | spark.application-name=Tests 3 | 4 | # Property should be specified but not used for local mode. 5 | spark.distributed-libraries= 6 | 7 | dou.training.set.csv.file.path= 8 | dou.training.set.parquet.2.file.path= 9 | dou.training.set.parquet.3.file.path= 10 | dou.training.set.parquet.vector.file.path= 11 | 12 | cat.dog.csv.file.path= 13 | cat.dog.training.set.parquet.file.path= 14 | cat.dog.test.set.parquet.file.path= 15 | 16 | mnist.csv.file.path= 17 | mnist.training.set.parquet.file.path= 18 | mnist.test.set.parquet.file.path= 19 | 20 | mnist.deep.learning.parquet.file.path= 21 | 22 | lyrics.training.set.directory.path= 23 | lyrics.model.directory.path= --------------------------------------------------------------------------------