Browse Source

first commit

placidenduwayo 2 years ago
parent
commit
717ebcba83

+ 8
- 0
pom.xml View File

@@ -66,6 +66,14 @@
66 66
             <version>2.1.2</version>
67 67
         </dependency>
68 68
 
69
+        <!-- https://mvnrepository.com/artifact/io.spray/spray-json -->
70
+        <dependency>
71
+            <groupId>io.spray</groupId>
72
+            <artifactId>spray-json_2.12</artifactId>
73
+            <version>1.3.6</version>
74
+        </dependency>
75
+
76
+
69 77
     </dependencies>
70 78
 
71 79
     <build>

+ 22
- 9
src/main/java/fr/natan/akkastreamfileprocessingapi/controller/MovieController.java View File

@@ -1,9 +1,11 @@
1 1
 package fr.natan.akkastreamfileprocessingapi.controller;
2 2
 
3
+import fr.natan.akkastreamfileprocessingapi.futurecompleteness.CompletableFutureResult;
3 4
 import fr.natan.akkastreamfileprocessingapi.models.Models;
4 5
 import fr.natan.akkastreamfileprocessingapi.service.AkkaStreamFileProcessing;
5 6
 import org.springframework.http.HttpStatus;
6 7
 import org.springframework.http.ResponseEntity;
8
+import org.springframework.scheduling.annotation.Async;
7 9
 import org.springframework.web.bind.annotation.PathVariable;
8 10
 import org.springframework.web.bind.annotation.RequestMapping;
9 11
 import org.springframework.web.bind.annotation.RequestMethod;
@@ -11,6 +13,10 @@ import org.springframework.web.bind.annotation.RestController;
11 13
 import scala.collection.IndexedSeq;
12 14
 import scala.concurrent.Future;
13 15
 
16
+import java.util.concurrent.CompletableFuture;
17
+import java.util.concurrent.ExecutionException;
18
+
19
+
14 20
 @SuppressWarnings("SpellCheckingInspection")
15 21
 @RestController
16 22
 public class MovieController {
@@ -22,29 +28,36 @@ public class MovieController {
22 28
     }
23 29
 
24 30
     @RequestMapping(value = "/persons/id/{personID}", method = RequestMethod.GET)
25
-    private Future<Models.Person> getPersonByID(@PathVariable(name = "personID") String nconst){
26
-
27
-       return akkaStreamFilesProcessing.getPersonById(nconst);
31
+    private ResponseEntity<String> getPersonByID(@PathVariable(name = "personID") String personID) throws ExecutionException, InterruptedException {
32
+        Future<Models.Person> personFuture = akkaStreamFilesProcessing.getPersonById(personID);
33
+        CompletableFuture<Models.Person> completableFutureResult =
34
+                new CompletableFutureResult().buildcompletableFuture(personFuture);
28 35
 
36
+        return new ResponseEntity<>(completableFutureResult.get().toString(), HttpStatus.OK);
29 37
     }
30 38
 
31 39
     @RequestMapping(value = "/persons/name/{primaryName}", method = RequestMethod.GET)
32
-    private Future<IndexedSeq<Models.Person>> getPersonByName(@PathVariable(name = "primaryName") String primaryName){
33
-        return akkaStreamFilesProcessing.getPersonByName(primaryName);
40
+    private ResponseEntity<IndexedSeq<String>> getPersonByName(@PathVariable(name = "primaryName") String primaryName) throws ExecutionException, InterruptedException {
41
+        Future<IndexedSeq<Models.Person>> personsFuture = akkaStreamFilesProcessing.getPersonByName(primaryName);
42
+        CompletableFuture completableFutureResult =new
43
+                CompletableFutureResult().buildCompletableFuture2(personsFuture);
44
+        IndexedSeq<String> list = (IndexedSeq<String>) completableFutureResult.get();
45
+        return new ResponseEntity<>(list, HttpStatus.OK);
34 46
     }
35 47
 
36 48
     @RequestMapping(value = "/tvseries/{tvseriePrimaryTitle}", method = RequestMethod.GET)
37
-    private Future<IndexedSeq<Models.TvSeries>> getTvserieByPrimaryTitle(@PathVariable(name ="tvseriePrimaryTitle" ) String tvseriePrimaryTitle){
49
+    private Future<IndexedSeq<Models.TvSeries>> getTvserieByPrimaryTitle(@PathVariable(name = "tvseriePrimaryTitle") String tvseriePrimaryTitle) {
38 50
         return akkaStreamFilesProcessing.getTvSerieByPrimaryTitle(tvseriePrimaryTitle);
39 51
     }
40 52
 
41 53
     @RequestMapping(value = "/tvseries/title/{tvSerieTitle}", method = RequestMethod.GET)
42
-    private Future<IndexedSeq<Models.Person>> getPersonsForTvSerie(@PathVariable(name = "tvSerieTitle") String tvSerieTitle){
43
-      return akkaStreamFilesProcessing.getTeamOfPersonsForTvSerie(tvSerieTitle);
54
+    @Async
55
+    private Future<IndexedSeq<Models.Person>> getPersonsForTvSerie(@PathVariable(name = "tvSerieTitle") String tvSerieTitle) {
56
+        return akkaStreamFilesProcessing.getTeamOfPersonsForTvSerie(tvSerieTitle);
44 57
     }
45 58
 
46 59
     @RequestMapping(value = "/persons", method = RequestMethod.GET)
47
-    private ResponseEntity<String> getAllPersons(){
60
+    private ResponseEntity<String> getAllPersons() {
48 61
         akkaStreamFilesProcessing.getAllPersons();
49 62
         return new ResponseEntity<>("is running", HttpStatus.OK);
50 63
     }

src/main/java/fr/natan/akkastreamfileprocessingapi/controller/BusinessExceptionHandler.java → src/main/java/fr/natan/akkastreamfileprocessingapi/exceptionshandler/BusinessExceptionHandler.java View File

@@ -1,4 +1,4 @@
1
-package fr.natan.akkastreamfileprocessingapi.controller;
1
+package fr.natan.akkastreamfileprocessingapi.exceptionshandler;
2 2
 
3 3
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.FileNotFoundException;
4 4
 import fr.natan.akkastreamfileprocessingapi.businessexceptions.MovieNotFoundException;

+ 31
- 0
src/main/java/fr/natan/akkastreamfileprocessingapi/futurecompleteness/CompletableFutureResult.java View File

@@ -0,0 +1,31 @@
1
+package fr.natan.akkastreamfileprocessingapi.futurecompleteness;
2
+
3
+import scala.collection.IndexedSeq;
4
+import scala.concurrent.Future;
5
+
6
+import java.util.concurrent.CompletableFuture;
7
+import java.util.concurrent.Executors;
8
+
9
+
10
+public class CompletableFutureResult<T> {
11
+
12
+    public CompletableFuture<T> buildcompletableFuture(Future<T> future){
13
+        CompletableFuture<T> completableFuture = new CompletableFuture<>();
14
+        Executors.newCachedThreadPool().submit(()->{
15
+            Thread.sleep(500);
16
+            return completableFuture.complete(future.value().get().get());
17
+        });
18
+        return completableFuture;
19
+    }
20
+
21
+    public CompletableFuture<IndexedSeq<T>> buildCompletableFuture2(Future<IndexedSeq<T>> futures){
22
+        CompletableFuture<IndexedSeq<T>> completableFuture = new CompletableFuture<>();
23
+        Executors.newCachedThreadPool().submit(
24
+                ()->{
25
+                    Thread.sleep(500);
26
+                    return completableFuture.complete(futures.value().get().get().seq());
27
+                }
28
+        );
29
+        return completableFuture;
30
+    }
31
+}

+ 6
- 11
src/main/scala/fr/natan/akkastreamfileprocessingapi/models/Models.scala View File

@@ -2,23 +2,18 @@ package fr.natan.akkastreamfileprocessingapi.models
2 2
 
3 3
 object Models {
4 4
 
5
-  final case class Person(
6
-                           nconst: String,
7
-                           primaryName: String,
8
-                           birthYear: String,
9
-                           deathYear: String,
10
-                           primaryProfession: List[String],
11
-                           knownForTitles: List[String]
12
-                         ) {
5
+  final case class Person(nconst: String, primaryName: String, birthYear: String, deathYear: String,
6
+                          primaryProfession: List[String], knownForTitles: List[String]) {
13 7
     override def toString: String = {
14 8
       "Person[person-ID:" + nconst +
15 9
         ", primary-name:" + primaryName +
16 10
         ", birth-year:" + birthYear +
17
-        ", dearth year:" + deathYear +
18
-        ", primary profession:" + primaryProfession +
19
-      ", known-for-titles"+knownForTitles+
11
+        ", dearth-year:" + deathYear +
12
+        ", primary-profession:" + primaryProfession +
13
+        ", known-for-titles" + knownForTitles +
20 14
         "]"
21 15
     }
16
+
22 17
   }
23 18
 
24 19
   final case class TvSeries(

+ 1
- 1
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/AkkaStreamFileProcessing.scala View File

@@ -6,7 +6,7 @@ import scala.concurrent.Future
6 6
 
7 7
 //noinspection SpellCheckingInspection,AccessorLikeMethodIsUnit
8 8
 trait AkkaStreamFileProcessing {
9
-  def getPersonById(nconst: String): Future[Person]
9
+  def getPersonById(personID: String): Future[Person]
10 10
   def getPersonByName(primaryName: String): Future[IndexedSeq[Person]]
11 11
 
12 12
   def getTvSerieByPrimaryTitle(tvSerieTitle: String):Future[IndexedSeq[TvSeries]]

+ 45
- 45
src/main/scala/fr/natan/akkastreamfileprocessingapi/service/AkkaStreamFileProcessingImpl.scala View File

@@ -26,10 +26,10 @@ class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessing {
26 26
   implicit val actorSystem: ActorSystem = ActorSystem("AkkaStreamActor")
27 27
   implicit val logger: Logger = Logger(LoggerFactory.getLogger(this.getClass))
28 28
 
29
-  override def getPersonById(nconst: String): Future[Person] = {
29
+  override def getPersonById(personID: String): Future[Person] = {
30 30
     val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
31
-    val res = source
32
-      .via(flow = filterByPersonIdFlow(nconst = nconst))
31
+    val res: Future[Person] = source
32
+      .via(flow = filterByPersonIdFlow(nconst = personID))
33 33
       .runWith(Sink.head)
34 34
 
35 35
     res.andThen {
@@ -90,11 +90,11 @@ class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessing {
90 90
     res
91 91
   }
92 92
 
93
-  private def getListOfPersonsIDByTvSerieID(tvSerieID: Future[Option[String]]): Future[IndexedSeq[Option[String]]] = {
93
+  private def getListOfPersonsIDByTvSerieID(tvSerieIdFuture: Future[Option[String]]): Future[IndexedSeq[Option[String]]] = {
94 94
     val source: Source[Map[String, String], _] = buildSource(inputFile = titlePrincipalsBasics)
95 95
     val res: Future[IndexedSeq[Option[String]]] = source
96 96
       .filter((rowMaps: Map[String, String]) => {
97
-        rowMaps.getOrElse(key = "tconst", default = "") == tvSerieID.value.get.get.get
97
+        rowMaps.getOrElse(key = "tconst", default = "") == tvSerieIdFuture.value.get.get.get
98 98
       })
99 99
       .map((rowMap: Map[String, String]) => {
100 100
         rowMap.get(key = "nconst")
@@ -104,18 +104,18 @@ class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessing {
104 104
     res
105 105
   }
106 106
 
107
-  private def getListOfPersonsForTvSerie(listPersonsIDs: Future[IndexedSeq[Option[String]]]): Future[IndexedSeq[Person]] = {
108
-    val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
107
+  private def getListOfPersonsForTvSerie(listPersonsIDsFuture: Future[IndexedSeq[Option[String]]]):
108
+  Future[IndexedSeq[Person]] = {
109 109
 
110
-    val res: Future[IndexedSeq[Person]] =
111
-      source
112
-        .filter((rowMaps: Map[String, String]) => {
113
-          listPersonsIDs.value.get.get.contains(rowMaps.get(key = "nconst"))
114
-        })
115
-        .map((rowMap: Map[String, String]) => {
116
-          buildPersonModel(rowMap)
117
-        })
118
-        .runWith(Sink.collection)
110
+    val source: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
111
+    val res: Future[IndexedSeq[Person]] = source
112
+      .filter((rowMaps: Map[String, String]) => {
113
+        listPersonsIDsFuture.value.get.get.contains(rowMaps.get(key = "nconst"))
114
+      })
115
+      .map((rowMap: Map[String, String]) => {
116
+        buildPersonModel(rowMap)
117
+      })
118
+      .runWith(Sink.collection)
119 119
 
120 120
     res
121 121
   }
@@ -126,39 +126,39 @@ class AkkaStreamFileProcessingImpl extends AkkaStreamFileProcessing {
126 126
     logger.info("STEP 1/3 START")
127 127
     val tvSerieIDFuture: Future[Option[String]] = getTvSerieIdByPrimaryTitle(primaryTitle = tvSeriePrimaryTitle)
128 128
 
129
-    val finalResult: Future[IndexedSeq[Person]] = tvSerieIDFuture.andThen({
130
-      case Failure(exception) => logger.error(s"$exception")
131
-      case Success(value: Option[String]) =>
132
-        logger.info(s"TvSerie ID: $value")
133
-        logger.info("STEP 1/3 END")
134
-    })
135
-      .flatMap({
136
-       _ =>
137
-         logger.info("STEP 2/3 START")
138
-         val listPersonIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(tvSerieID = tvSerieIDFuture)
139
-          listPersonIDsFuture.andThen({
140
-            case Failure(exception) => logger.error(s"$exception")
141
-            case Success(value) =>
142
-              value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
143
-              logger.info("STEP 2/3 END")
144
-          })
145
-            .flatMap({
146
-              future =>
147
-                logger.info("STEP 3/3 START")
148
-                val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(listPersonsIDs = listPersonIDsFuture)
149
-                personsTeamFuture.andThen({
150
-                  case Failure(exception) => logger.error(s"$exception")
151
-                  case Success(value: IndexedSeq[Person]) =>
152
-                    value.foreach((person: Person) => logger.info(s"${person.toString}"))
153
-                    logger.info("STEP 3/3 END")
154
-                })
155
-            })
129
+    val finalFuture: Future[IndexedSeq[Person]] =
130
+      tvSerieIDFuture.andThen({
131
+        case Failure(exception) => logger.error(s"$exception")
132
+        case Success(value: Option[String]) =>
133
+          logger.info(s"TvSerie ID: $value")
134
+          logger.info("STEP 1/3 END")
156 135
       })
136
+        .flatMap({
137
+          _ =>
138
+            logger.info("STEP 2/3 START")
139
+            val listPersonIDsFuture: Future[IndexedSeq[Option[String]]] = getListOfPersonsIDByTvSerieID(tvSerieIdFuture = tvSerieIDFuture)
140
+            listPersonIDsFuture.andThen({
141
+              case Failure(exception) => logger.error(s"$exception")
142
+              case Success(value) =>
143
+                value.foreach((personID: Option[String]) => logger.info(s"Person ID:$personID"))
144
+                logger.info("STEP 2/3 END")
145
+            })
146
+              .flatMap({
147
+                future =>
148
+                  logger.info("STEP 3/3 START")
149
+                  val personsTeamFuture: Future[IndexedSeq[Person]] = getListOfPersonsForTvSerie(listPersonsIDsFuture = listPersonIDsFuture)
150
+                  personsTeamFuture.andThen({
151
+                    case Failure(exception) => logger.error(s"$exception")
152
+                    case Success(value: IndexedSeq[Person]) =>
153
+                      value.foreach((person: Person) => logger.info(s"${person.toString}"))
154
+                      logger.info("STEP 3/3 END")
155
+                  })
156
+              })
157
+        })
157 158
 
158
-    finalResult
159
+    finalFuture
159 160
   }
160 161
 
161
-
162 162
   override def getAllPersons(): Unit = {
163 163
     val personSource: Source[Map[String, String], _] = buildSource(inputFile = nameBasics)
164 164
     //graph

Powered by TurnKey Linux.