├── .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=
--------------------------------------------------------------------------------