From 55d77e7d2b5ddd2fe056f29565509e7efa1679ac Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 24 May 2019 15:36:03 +0200 Subject: [PATCH 1/3] fixed error and added @NotNull/@Nullable annotations - The RenderResponse class now has an "error" property in case the renderer threw an error - The whole project was given @NotNull/@Nullable annotation to improve code quality --- .../angularjuniversal/data/DataLoader.java | 5 ++ .../angularjuniversal/keywords/Keyword.java | 15 ++++-- .../keywords/KeywordService.java | 5 ++ .../pom.xml | 2 +- .../springboot/simple/WebApplication.java | 15 +++++- .../pom.xml | 2 +- .../ApplicationConfiguration.java | 3 +- .../keywords/KeywordController.java | 3 ++ .../tcprenderer/TcpRenderEngine.java | 46 +++++++++++++--- .../tcprenderer/TcpRenderEngineFactory.java | 2 + .../tcprenderer/TcpRequest.java | 21 ++++++-- .../tcprenderer/TcpResponse.java | 36 ++++++++++++- .../angularjuniversal/renderer/Renderer.java | 18 +++++-- .../configuration/RenderConfiguration.java | 54 +++++++++++++++---- .../renderer/engine/RenderEngine.java | 3 +- .../renderer/engine/RenderEngineFactory.java | 3 ++ .../renderer/exception/RenderException.java | 18 +++++++ .../renderer/request/RenderRequest.java | 10 +++- .../renderer/utils/RenderUtils.java | 6 ++- .../pom.xml | 6 +++ .../AngularJUniversalAutoConfiguration.java | 30 ++++++++--- .../starter/AngularJUniversalConfigurer.java | 7 ++- .../starter/AngularJUniversalProperties.java | 25 ++++++--- .../starter/AngularJUniversalUtils.java | 10 ++-- .../starter/AngularJUniversalView.java | 8 ++- .../AngularJUniversalViewResolver.java | 12 +++-- pom.xml | 15 +++++- 27 files changed, 316 insertions(+), 64 deletions(-) create mode 100644 angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/exception/RenderException.java diff --git a/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/data/DataLoader.java b/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/data/DataLoader.java index 60ac674..c661ce3 100644 --- a/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/data/DataLoader.java +++ b/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/data/DataLoader.java @@ -1,5 +1,8 @@ package ch.swaechter.angularjuniversal.data; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.InputStream; /** @@ -14,6 +17,7 @@ public class DataLoader { * * @return Input stream of the index template */ + @Nullable public InputStream getIndexAsInputStream() { return this.getClass().getResourceAsStream("/public/index.html"); } @@ -23,6 +27,7 @@ public InputStream getIndexAsInputStream() { * * @return Input stream of the server bundle */ + @Nullable public InputStream getServerBundleAsInputStream() { return this.getClass().getResourceAsStream("/server.js"); } diff --git a/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/Keyword.java b/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/Keyword.java index 9c56666..b290dfa 100644 --- a/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/Keyword.java +++ b/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/Keyword.java @@ -1,5 +1,7 @@ package ch.swaechter.angularjuniversal.keywords; +import org.jetbrains.annotations.NotNull; + /** * This class is responsible for representing a keyword with a name. * @@ -10,17 +12,21 @@ public class Keyword { /** * ID of the keyword. */ + @NotNull private Integer id; /** * Name of the keyword. */ + @NotNull private String name; /** * Default constructor. */ public Keyword() { + this.id = (int) Math.round(Math.random() * Integer.MAX_VALUE); + this.name = ""; } /** @@ -29,7 +35,7 @@ public Keyword() { * @param id ID of the keyword * @param name Name of the keyword */ - public Keyword(Integer id, String name) { + public Keyword(@NotNull Integer id, @NotNull String name) { this.id = id; this.name = name; } @@ -39,6 +45,7 @@ public Keyword(Integer id, String name) { * * @return ID of the keyword */ + @NotNull public Integer getId() { return id; } @@ -48,8 +55,7 @@ public Integer getId() { * * @param id New ID of the keyword */ - - public void setId(Integer id) { + public void setId(@NotNull Integer id) { this.id = id; } @@ -58,6 +64,7 @@ public void setId(Integer id) { * * @return Name of the keyword */ + @NotNull public String getName() { return name; } @@ -67,7 +74,7 @@ public String getName() { * * @param name New name of the keyword */ - public void setName(String name) { + public void setName(@NotNull String name) { this.name = name; } } diff --git a/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/KeywordService.java b/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/KeywordService.java index 691a024..1c58df4 100644 --- a/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/KeywordService.java +++ b/angularj-universal-application/src/main/java/ch/swaechter/angularjuniversal/keywords/KeywordService.java @@ -1,5 +1,7 @@ package ch.swaechter.angularjuniversal.keywords; +import org.jetbrains.annotations.NotNull; + import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -11,6 +13,7 @@ */ public class KeywordService { + @NotNull private final List keywords; public KeywordService() { @@ -25,6 +28,7 @@ public KeywordService() { * * @return All keywords as list */ + @NotNull public List getKeywords() { return keywords; } @@ -35,6 +39,7 @@ public List getKeywords() { * @param id ID of the keyword * @return Optional keyword */ + @NotNull public Optional getKeyword(int id) { if (id >= 0 && id < keywords.size()) { return Optional.of(keywords.get(id)); diff --git a/angularj-universal-example-spring-boot-simple/pom.xml b/angularj-universal-example-spring-boot-simple/pom.xml index 2ffb19d..28dba57 100644 --- a/angularj-universal-example-spring-boot-simple/pom.xml +++ b/angularj-universal-example-spring-boot-simple/pom.xml @@ -51,7 +51,7 @@ maven-compiler-plugin 3.7.0 - 1.8 + 1.11 1.8 diff --git a/angularj-universal-example-spring-boot-simple/src/main/java/ch/swaechter/angularjuniversal/example/springboot/simple/WebApplication.java b/angularj-universal-example-spring-boot-simple/src/main/java/ch/swaechter/angularjuniversal/example/springboot/simple/WebApplication.java index 6b29646..893f639 100644 --- a/angularj-universal-example-spring-boot-simple/src/main/java/ch/swaechter/angularjuniversal/example/springboot/simple/WebApplication.java +++ b/angularj-universal-example-spring-boot-simple/src/main/java/ch/swaechter/angularjuniversal/example/springboot/simple/WebApplication.java @@ -7,6 +7,7 @@ import ch.swaechter.angularjuniversal.renderer.engine.RenderEngineFactory; import ch.swaechter.angularjuniversal.renderer.utils.RenderUtils; import ch.swaechter.angularjuniversal.tcprenderer.TcpRenderEngineFactory; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -32,33 +33,38 @@ public static void main(String[] args) { @RestController public class ContentController { + @NotNull private final RenderService renderService; @Autowired - public ContentController(RenderService renderService) { + public ContentController(@NotNull RenderService renderService) { this.renderService = renderService; } @ResponseBody @GetMapping({"/", "/home"}) + @NotNull public String showHome() throws Exception { return renderService.renderPage("/home").get(); } @ResponseBody @GetMapping("/keywords") + @NotNull public String showLogin() throws Exception { return renderService.renderPage("/keywords").get(); } @ResponseBody @GetMapping("/keywords/{id}") + @NotNull public String showLogout(@PathVariable("id") int id) throws Exception { return renderService.renderPage("/keywords/" + id).get(); } @ResponseBody @GetMapping("/about") + @NotNull public String showPage() throws Exception { return renderService.renderPage("/about").get(); } @@ -68,6 +74,7 @@ public String showPage() throws Exception { @RequestMapping("/api") public class KeywordController { + @NotNull private final KeywordService keywordService; public KeywordController() { @@ -75,6 +82,7 @@ public KeywordController() { } @GetMapping("/keyword") + @NotNull public ResponseEntity> getKeywords() { return new ResponseEntity<>(keywordService.getKeywords(), HttpStatus.OK); } @@ -83,8 +91,10 @@ public ResponseEntity> getKeywords() { @Service public class RenderService { + @NotNull private final Renderer renderer; + @NotNull public RenderService() throws IOException { // Load the template and create a temporary server bundle file from the resource (This file will of course never change until manually edited) InputStream templateInputStream = getClass().getResourceAsStream("/public/index.html"); @@ -105,7 +115,8 @@ public RenderService() throws IOException { this.renderer.startRenderer(); } - Future renderPage(String uri) { + @NotNull + Future renderPage(@NotNull String uri) { // Render a request and return a resolvable future return renderer.addRenderRequest(uri); } diff --git a/angularj-universal-example-spring-boot/pom.xml b/angularj-universal-example-spring-boot/pom.xml index cee40a7..7a53906 100644 --- a/angularj-universal-example-spring-boot/pom.xml +++ b/angularj-universal-example-spring-boot/pom.xml @@ -56,7 +56,7 @@ maven-compiler-plugin 3.7.0 - 1.8 + 1.11 1.8 diff --git a/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/configuration/ApplicationConfiguration.java b/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/configuration/ApplicationConfiguration.java index a91459d..ea87a1f 100644 --- a/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/configuration/ApplicationConfiguration.java +++ b/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/configuration/ApplicationConfiguration.java @@ -1,5 +1,6 @@ package ch.swaechter.angularjuniversal.example.springboot.configuration; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -8,7 +9,7 @@ public class ApplicationConfiguration implements WebMvcConfigurer { @Override - public void addCorsMappings(CorsRegistry corsRegistry) { + public void addCorsMappings(@NotNull CorsRegistry corsRegistry) { corsRegistry.addMapping("/**").allowedOrigins("http://localhost:4200"); } } diff --git a/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/keywords/KeywordController.java b/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/keywords/KeywordController.java index ddd504a..eb7bf27 100644 --- a/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/keywords/KeywordController.java +++ b/angularj-universal-example-spring-boot/src/main/java/ch/swaechter/angularjuniversal/example/springboot/keywords/KeywordController.java @@ -2,6 +2,7 @@ import ch.swaechter.angularjuniversal.keywords.Keyword; import ch.swaechter.angularjuniversal.keywords.KeywordService; +import org.jetbrains.annotations.NotNull; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -19,6 +20,7 @@ @RequestMapping("/api") public class KeywordController { + @NotNull private final KeywordService keywordService; /** @@ -34,6 +36,7 @@ public KeywordController() { * @return All keywords */ @GetMapping("/keyword") + @NotNull public ResponseEntity> getKeywords() { return new ResponseEntity<>(keywordService.getKeywords(), HttpStatus.OK); } diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java index a796b00..1af03fc 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java @@ -2,8 +2,11 @@ import ch.swaechter.angularjuniversal.renderer.configuration.RenderConfiguration; import ch.swaechter.angularjuniversal.renderer.engine.RenderEngine; +import ch.swaechter.angularjuniversal.renderer.exception.RenderException; import ch.swaechter.angularjuniversal.renderer.request.RenderRequest; import com.fasterxml.jackson.databind.ObjectMapper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -23,18 +26,19 @@ public class TcpRenderEngine implements RenderEngine { /** * Name of the environment variable passed to Node.js to indicate the port. */ + @NotNull private static final String NODE_PORT_ENVIRONMENT_VARIABLE_NAME = "NODEPORT"; /** * Object mapper used to serialize/deserialize TCP request and responses. */ - private final ObjectMapper objectMapper; + @NotNull + private final ObjectMapper objectMapper = new ObjectMapper(); /** * Create a new TCP based render engine that will access a NodeJS server for rendering */ public TcpRenderEngine() { - this.objectMapper = new ObjectMapper(); } /** @@ -45,36 +49,62 @@ public TcpRenderEngine() { * @param renderConfiguration Render configuration with the all required information */ @Override - public void startWorking(BlockingQueue> renderRequests, RenderConfiguration renderConfiguration) { + public void startWorking(@NotNull BlockingQueue> renderRequests, @NotNull RenderConfiguration renderConfiguration) { try { // Start the Node.js render service + @NotNull ProcessBuilder processBuilder = new ProcessBuilder(renderConfiguration.getNodePath(), renderConfiguration.getServerBundleFile().getAbsolutePath()); + @NotNull Map processEnvironment = processBuilder.environment(); processEnvironment.put(NODE_PORT_ENVIRONMENT_VARIABLE_NAME, String.valueOf(renderConfiguration.getNodePort())); + + @NotNull Process process = processBuilder.start(); while (true) { Optional renderRequestItem = renderRequests.take(); + if (renderRequestItem.isPresent()) { - try { - // Get the render request item - RenderRequest renderRequest = renderRequestItem.get(); + // Get the render request item + @NotNull + RenderRequest renderRequest = renderRequestItem.get(); + try { // Create the socket and initialize the writer reader + @NotNull Socket socket = new Socket("localhost", renderConfiguration.getNodePort()); + @NotNull PrintWriter writer = new PrintWriter(socket.getOutputStream(), true); + @NotNull BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // Write the request + @NotNull TcpRequest tcpRequest = new TcpRequest(renderRequest.getUuid(), renderRequest.getUri(), renderConfiguration.getTemplateContent()); writer.println(objectMapper.writeValueAsString(tcpRequest)); writer.flush(); // Read the response + @NotNull TcpResponse tcpResponse = objectMapper.readValue(reader, TcpResponse.class); - renderRequest.getFuture().complete(tcpResponse.getHtml()); - } catch (Exception exception) { + + // Get the error message if an error occurred on the render server + @Nullable + String errorMessage = tcpResponse.getError(); + + // check if an error occurred + if (errorMessage == null) { + renderRequest.getFuture().complete(tcpResponse.getHtml()); + } else { + throw new RenderException(errorMessage); + } + } catch (Throwable exception) { exception.printStackTrace(); + if (exception instanceof RenderException) { + renderRequest.getFuture().completeExceptionally(exception); + } else { + renderRequest.getFuture().completeExceptionally(new RenderException(exception)); + } } } else { process.destroy(); diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngineFactory.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngineFactory.java index c1aa315..222e4e2 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngineFactory.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngineFactory.java @@ -2,6 +2,7 @@ import ch.swaechter.angularjuniversal.renderer.engine.RenderEngine; import ch.swaechter.angularjuniversal.renderer.engine.RenderEngineFactory; +import org.jetbrains.annotations.NotNull; /** * Provide a TCP render engine factory which is able to create new TCP render engines. @@ -16,6 +17,7 @@ public class TcpRenderEngineFactory implements RenderEngineFactory { * @return New TCP render engine */ @Override + @NotNull public RenderEngine createRenderEngine() { return new TcpRenderEngine(); } diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java index b0b368a..2df04f3 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java @@ -1,5 +1,9 @@ package ch.swaechter.angularjuniversal.tcprenderer; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + /** * TCP request representing the JSON object sent to the render server. * @@ -10,22 +14,28 @@ public class TcpRequest { /** * ID of the render request. */ + @NotNull private String id; /** * URL of the render request. */ + @NotNull private String url; /** * Fallback document template. */ + @NotNull private String document; /** * Default constructor for Jackson */ public TcpRequest() { + this.id = UUID.randomUUID().toString(); + this.url = ""; + this.document = ""; } /** @@ -35,7 +45,7 @@ public TcpRequest() { * @param url URL of the render request * @param document Fallback document template */ - public TcpRequest(String id, String url, String document) { + public TcpRequest(@NotNull String id, @NotNull String url, @NotNull String document) { this.id = id; this.url = url; this.document = document; @@ -46,6 +56,7 @@ public TcpRequest(String id, String url, String document) { * * @return ID of the request */ + @NotNull public String getId() { return id; } @@ -55,7 +66,7 @@ public String getId() { * * @param id New ID of the request */ - public void setId(String id) { + public void setId(@NotNull String id) { this.id = id; } @@ -64,6 +75,7 @@ public void setId(String id) { * * @return ID of the request */ + @NotNull public String getUrl() { return url; } @@ -73,7 +85,7 @@ public String getUrl() { * * @param url New URL of the request */ - public void setUrl(String url) { + public void setUrl(@NotNull String url) { this.url = url; } @@ -82,6 +94,7 @@ public void setUrl(String url) { * * @return Fallback document template of the request */ + @NotNull public String getDocument() { return document; } @@ -91,7 +104,7 @@ public String getDocument() { * * @param document New fallback document template of the request */ - public void setDocument(String document) { + public void setDocument(@NotNull String document) { this.document = document; } } diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java index e955936..8d65cf4 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java @@ -1,5 +1,8 @@ package ch.swaechter.angularjuniversal.tcprenderer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + /** * TCP response represeing the JSON object with the rendered page from the server. * @@ -10,13 +13,21 @@ public class TcpResponse { /** * Rendered HTML in the response. */ + @Nullable private String html; /** * ID of the render response. */ + @NotNull private String id; + /** + * The error if one occurred + */ + @Nullable + private String error; + /** * Default constructor for Jackson */ @@ -28,6 +39,7 @@ public TcpResponse() { * * @return Rendered HTML of the response */ + @Nullable public String getHtml() { return html; } @@ -37,7 +49,7 @@ public String getHtml() { * * @param html New rendered HTML of the response */ - public void setHtml(String html) { + public void setHtml(@Nullable String html) { this.html = html; } @@ -46,6 +58,7 @@ public void setHtml(String html) { * * @return ID of the response */ + @NotNull public String getId() { return id; } @@ -55,7 +68,26 @@ public String getId() { * * @param id New ID of the response */ - public void setId(String id) { + public void setId(@NotNull String id) { this.id = id; } + + /** + * Get the occurred error if one occurred + * + * @return the error description + */ + @Nullable + public String getError() { + return error; + } + + /** + * Set the error if one occurred + * + * @param error the error description + */ + public void setError(@Nullable String error) { + this.error = error; + } } diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/Renderer.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/Renderer.java index b58192d..9061501 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/Renderer.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/Renderer.java @@ -4,6 +4,8 @@ import ch.swaechter.angularjuniversal.renderer.engine.RenderEngine; import ch.swaechter.angularjuniversal.renderer.engine.RenderEngineFactory; import ch.swaechter.angularjuniversal.renderer.request.RenderRequest; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.Date; @@ -22,27 +24,31 @@ public class Renderer { /** * Queue with all active render requests. */ + @NotNull private final BlockingQueue> renderRequests; /** * Render configuration with all important information. */ + @NotNull private final RenderConfiguration renderConfiguration; /** * Render engine factory for creating new render requests. */ - + @NotNull private final RenderEngineFactory renderEngineFactory; /** * Current render engine. */ + @Nullable private RenderEngine renderEngine; /** * Date of the server bundle file, used for live reloading. */ + @Nullable private Date startDate; /** @@ -52,7 +58,7 @@ public class Renderer { * @param renderConfiguration Render configuration used as main configuration * @param renderEngineFactory Render engine factory used for creating new render engines */ - public Renderer(RenderConfiguration renderConfiguration, RenderEngineFactory renderEngineFactory) { + public Renderer(@NotNull RenderConfiguration renderConfiguration, @NotNull RenderEngineFactory renderEngineFactory) { this.renderRequests = new LinkedBlockingDeque<>(); this.renderConfiguration = renderConfiguration; this.renderEngineFactory = renderEngineFactory; @@ -68,12 +74,15 @@ public synchronized void startRenderer() { startDate = new Date(); renderEngine = renderEngineFactory.createRenderEngine(); + @NotNull Thread engineThread = new Thread(() -> renderEngine.startWorking(renderRequests, renderConfiguration)); engineThread.start(); if (renderConfiguration.getLiveReload()) { + @NotNull Thread reloadThread = new Thread(() -> { while (isRendererRunning()) { + @Nullable File file = renderConfiguration.getServerBundleFile(); if (startDate.before(new Date(file.lastModified()))) { stopRenderer(); @@ -96,8 +105,9 @@ public synchronized void stopRenderer() { renderRequests.add(Optional.empty()); + // Wait for an empty request queue while (renderRequests.size() != 0) { - // Wait for an empty request queue + Thread.yield(); } renderEngine = null; @@ -118,7 +128,9 @@ public synchronized boolean isRendererRunning() { * @param uri URI of the render request * @return Future that can be accessed later on to get the rendered content */ + @NotNull public Future addRenderRequest(String uri) { + @NotNull RenderRequest renderRequest = new RenderRequest(uri); renderRequests.add(Optional.of(renderRequest)); return renderRequest.getFuture(); diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/configuration/RenderConfiguration.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/configuration/RenderConfiguration.java index dba9f3a..5eb1c98 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/configuration/RenderConfiguration.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/configuration/RenderConfiguration.java @@ -1,5 +1,9 @@ package ch.swaechter.angularjuniversal.renderer.configuration; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.io.File; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -16,36 +20,43 @@ public class RenderConfiguration { /** * Path or executable name of the Node.js executable. This path is used to start a Node.js process for rendering. */ + @NotNull private final String nodePath; /** * Port of the Node.js process is opening a TCP server. */ + @NotNull private final Integer nodePort; /** * File of the server bundle. */ + @NotNull private final File serverBundleFile; /** * Content of the template. */ + @NotNull private final String templateContent; /** * Status of live reload */ + @NotNull private final Boolean liveReload; /** * Charset of the application. */ + @NotNull private final Charset charset; /** * Routes of the application. */ + @NotNull private final List routes; /** @@ -58,7 +69,8 @@ public class RenderConfiguration { * @param liveReload Status if live reload is enabled or not * @param routes Routes of the application */ - private RenderConfiguration(String nodePath, Integer nodePort, File serverBundleFile, String templateContent, Boolean liveReload, Charset charset, List routes) { + @Contract(pure = true) + private RenderConfiguration(@NotNull String nodePath, @NotNull Integer nodePort, @NotNull File serverBundleFile, @NotNull String templateContent, @NotNull Boolean liveReload, @NotNull Charset charset, @NotNull List routes) { this.nodePath = nodePath; this.nodePort = nodePort; this.serverBundleFile = serverBundleFile; @@ -73,6 +85,8 @@ private RenderConfiguration(String nodePath, Integer nodePort, File serverBundle * * @return Path or executable Node.js name */ + @NotNull + @Contract(pure = true) public String getNodePath() { return nodePath; } @@ -82,6 +96,8 @@ public String getNodePath() { * * @return TCP port used for the communication */ + @NotNull + @Contract(pure = true) public Integer getNodePort() { return nodePort; } @@ -91,6 +107,8 @@ public Integer getNodePort() { * * @return File path of the server bundle */ + @NotNull + @Contract(pure = true) public File getServerBundleFile() { return serverBundleFile; } @@ -100,6 +118,8 @@ public File getServerBundleFile() { * * @return Content of the template */ + @NotNull + @Contract(pure = true) public String getTemplateContent() { return templateContent; } @@ -109,6 +129,8 @@ public String getTemplateContent() { * * @return Status of live reload */ + @NotNull + @Contract(pure = true) public Boolean getLiveReload() { return liveReload; } @@ -118,6 +140,8 @@ public Boolean getLiveReload() { * * @return Charset of the application */ + @NotNull + @Contract(pure = true) public Charset getCharset() { return charset; } @@ -127,6 +151,8 @@ public Charset getCharset() { * * @return Routes of the application */ + @NotNull + @Contract(pure = true) public List getRoutes() { return routes; } @@ -141,44 +167,45 @@ public static class RenderConfigurationBuilder { /** * Path or executable name of the Node.js executable. This path is used to start a Node.js process for rendering. */ + @NotNull private final String nodePath; /** * Port of the Node.js process is opening a TCP server. */ + @NotNull private final Integer nodePort; /** * Content of the template. */ + @NotNull private final String templateContent; /** * File of the server bundle. */ + @NotNull private final File serverBundleFile; /** * Status of live reload */ + @NotNull private Boolean liveReload = false; /** * Charset of the application. */ + @NotNull private Charset charset = StandardCharsets.UTF_8; /** * Routes of the application. */ + @NotNull private List routes = Arrays.asList("/"); - /** - * Create a new render configuration builder that can be used to build the render configuration. - * - * @param templateContent Content of the template used for rendering - * @param serverBundleFile Server bundle file used for rendering - */ /** * Create a new render configuration builder that can be used to build the render configuration. * @@ -187,7 +214,7 @@ public static class RenderConfigurationBuilder { * @param serverBundleFile Server bundle file used for rendering * @param templateContent Content of the template used for rendering */ - public RenderConfigurationBuilder(String nodePath, Integer nodePort, File serverBundleFile, String templateContent) { + public RenderConfigurationBuilder(@NotNull String nodePath, @NotNull Integer nodePort, @NotNull File serverBundleFile, @NotNull String templateContent) { this.nodePath = nodePath; this.nodePort = nodePort; this.templateContent = templateContent; @@ -200,6 +227,8 @@ public RenderConfigurationBuilder(String nodePath, Integer nodePort, File server * @param liveReload Status of live reloading * @return Current render configuration builder */ + @NotNull + @Contract(value = "_ -> this") public RenderConfigurationBuilder liveReload(boolean liveReload) { this.liveReload = liveReload; return this; @@ -211,7 +240,9 @@ public RenderConfigurationBuilder liveReload(boolean liveReload) { * @param charset Charset of the application * @return Current render configuration builder */ - public RenderConfigurationBuilder charset(Charset charset) { + @NotNull + @Contract(value = "_ -> this") + public RenderConfigurationBuilder charset(@NotNull Charset charset) { this.charset = charset; return this; } @@ -222,7 +253,9 @@ public RenderConfigurationBuilder charset(Charset charset) { * @param routes Routes of the application * @return Current render configuration builder */ - public RenderConfigurationBuilder routes(List routes) { + @NotNull + @Contract(value = "_ -> this") + public RenderConfigurationBuilder routes(@NotNull List routes) { this.routes = routes; return this; } @@ -232,6 +265,7 @@ public RenderConfigurationBuilder routes(List routes) { * * @return New render configuration */ + @NotNull public RenderConfiguration build() { return new RenderConfiguration(nodePath, nodePort, serverBundleFile, templateContent, liveReload, charset, routes); } diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngine.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngine.java index 3a95496..6339e7e 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngine.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngine.java @@ -2,6 +2,7 @@ import ch.swaechter.angularjuniversal.renderer.configuration.RenderConfiguration; import ch.swaechter.angularjuniversal.renderer.request.RenderRequest; +import org.jetbrains.annotations.NotNull; import java.util.Optional; import java.util.concurrent.BlockingQueue; @@ -22,5 +23,5 @@ public interface RenderEngine { * @param renderRequests Blocking queue with requests to read from * @param renderConfiguration Render configuration with the all required information */ - void startWorking(BlockingQueue> renderRequests, RenderConfiguration renderConfiguration); + void startWorking(@NotNull BlockingQueue> renderRequests, @NotNull RenderConfiguration renderConfiguration); } diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngineFactory.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngineFactory.java index 48cf857..c44ba06 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngineFactory.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/engine/RenderEngineFactory.java @@ -1,5 +1,7 @@ package ch.swaechter.angularjuniversal.renderer.engine; +import org.jetbrains.annotations.NotNull; + /** * This interface is used to create new render engines. * @@ -12,5 +14,6 @@ public interface RenderEngineFactory { * * @return New render engine */ + @NotNull RenderEngine createRenderEngine(); } diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/exception/RenderException.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/exception/RenderException.java new file mode 100644 index 0000000..6402aee --- /dev/null +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/exception/RenderException.java @@ -0,0 +1,18 @@ +package ch.swaechter.angularjuniversal.renderer.exception; + +import org.jetbrains.annotations.NotNull; + +/** + * An Exception thrown during Rendering either by a remote renderer or locally by the rendering routine + */ +public class RenderException extends IllegalStateException { + + public RenderException(@NotNull String errorMessage) { + super(errorMessage); + } + + public RenderException(@NotNull Throwable cause) { + super(cause); + } + +} diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java index 71e80a5..60be6c2 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java @@ -1,5 +1,7 @@ package ch.swaechter.angularjuniversal.renderer.request; +import org.jetbrains.annotations.NotNull; + import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -14,16 +16,19 @@ public class RenderRequest { /** * Completable future that will contain the rendered content. */ + @NotNull private CompletableFuture future; /** * Unique UUID of the request. */ + @NotNull private String uuid; /** * URI of the request. */ + @NotNull private String uri; /** @@ -31,7 +36,7 @@ public class RenderRequest { * * @param uri URI of the page request */ - public RenderRequest(String uri) { + public RenderRequest(@NotNull String uri) { this.future = new CompletableFuture<>(); this.uuid = UUID.randomUUID().toString(); this.uri = uri; @@ -42,6 +47,7 @@ public RenderRequest(String uri) { * * @return Completable future of the render request */ + @NotNull public CompletableFuture getFuture() { return future; } @@ -51,6 +57,7 @@ public CompletableFuture getFuture() { * * @return Unique UUID of the render request */ + @NotNull public String getUuid() { return uuid; } @@ -60,6 +67,7 @@ public String getUuid() { * * @return URI of the render request */ + @NotNull public String getUri() { return uri; } diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/utils/RenderUtils.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/utils/RenderUtils.java index 5c0e8ec..ea420db 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/utils/RenderUtils.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/utils/RenderUtils.java @@ -1,5 +1,7 @@ package ch.swaechter.angularjuniversal.renderer.utils; +import org.jetbrains.annotations.NotNull; + import java.io.*; import java.nio.charset.Charset; @@ -18,7 +20,7 @@ public class RenderUtils { * @return Input stream content as string * @throws IOException Exception in case of an IO problem */ - public static String getStringFromInputStream(InputStream inputStream, Charset charset) throws IOException { + public static String getStringFromInputStream(@NotNull InputStream inputStream, @NotNull Charset charset) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int result = inputStream.read(); while (result != -1) { @@ -38,7 +40,7 @@ public static String getStringFromInputStream(InputStream inputStream, Charset c * @return Newly created temporary file * @throws IOException Exception in case of an IO problem */ - public static File createTemporaryFileFromInputStream(String suffix, String prefix, InputStream inputStream) throws IOException { + public static File createTemporaryFileFromInputStream(@NotNull String suffix, @NotNull String prefix, @NotNull InputStream inputStream) throws IOException { File file = File.createTempFile(suffix, prefix); file.deleteOnExit(); diff --git a/angularj-universal-spring-boot-starter/pom.xml b/angularj-universal-spring-boot-starter/pom.xml index bf2ea6d..179ea56 100644 --- a/angularj-universal-spring-boot-starter/pom.xml +++ b/angularj-universal-spring-boot-starter/pom.xml @@ -46,5 +46,11 @@ 2.1.1.RELEASE test + + org.springframework.boot + spring-boot-configuration-processor + 2.1.1.RELEASE + true + diff --git a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalAutoConfiguration.java b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalAutoConfiguration.java index 1088031..059c965 100644 --- a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalAutoConfiguration.java +++ b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalAutoConfiguration.java @@ -5,6 +5,8 @@ import ch.swaechter.angularjuniversal.renderer.engine.RenderEngineFactory; import ch.swaechter.angularjuniversal.renderer.utils.RenderUtils; import ch.swaechter.angularjuniversal.tcprenderer.TcpRenderEngineFactory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; @@ -37,6 +39,7 @@ public class AngularJUniversalAutoConfiguration { */ @Bean @ConditionalOnMissingBean + @NotNull public RenderEngineFactory getRenderEngineFactory() { return new TcpRenderEngineFactory(); } @@ -50,21 +53,26 @@ public RenderEngineFactory getRenderEngineFactory() { */ @Bean @ConditionalOnMissingBean - public RenderConfiguration getRenderConfiguration(AngularJUniversalProperties properties, ResourceLoader resourceLoader) { + @NotNull + public RenderConfiguration getRenderConfiguration(@NotNull AngularJUniversalProperties properties, @NotNull ResourceLoader resourceLoader) { // Check the charset if (properties.getCharset() == null) { throw new RuntimeException("AngularJ Universal starter is unable to parse the charset"); } // Get the Node.js path + @NotNull String nodePath = properties.getNodePath(); // Get the Node.js port + @NotNull Integer nodePort = properties.getNodePort(); // Create a temporary server bundle from the input stream + @Nullable File serverBundleFile; try { + @NotNull InputStream serverBundleInputStream = AngularJUniversalUtils.getInputStreamFromResource(resourceLoader, properties.getServerBundleResourcePath()); serverBundleFile = RenderUtils.createTemporaryFileFromInputStream("serverbundle", ".js", serverBundleInputStream); } catch (IOException exception) { @@ -72,8 +80,10 @@ public RenderConfiguration getRenderConfiguration(AngularJUniversalProperties pr } // Get the content of the index template + @Nullable String templateContent; try { + @NotNull InputStream indexInputStream = AngularJUniversalUtils.getInputStreamFromResource(resourceLoader, properties.getIndexResourcePath()); templateContent = RenderUtils.getStringFromInputStream(indexInputStream, properties.getCharset()); } catch (IOException exception) { @@ -85,13 +95,14 @@ public RenderConfiguration getRenderConfiguration(AngularJUniversalProperties pr builder.charset(properties.getCharset()); // Check the routes + @NotNull List routes = properties.getRoutes(); - if (!properties.getRoutes().isEmpty()) { - builder.routes(routes); - } else { + if (properties.getRoutes().isEmpty()) { throw new RuntimeException("AngularJ Universal starter is unable to parse and find any routes for " + properties.getRoutes()); } + builder.routes(routes); + // Build the render configuration return builder.build(); } @@ -105,8 +116,10 @@ public RenderConfiguration getRenderConfiguration(AngularJUniversalProperties pr */ @Bean @ConditionalOnMissingBean - public Renderer getRenderer(RenderEngineFactory renderEngineFactory, RenderConfiguration renderConfiguration) { + @NotNull + public Renderer getRenderer(@NotNull RenderEngineFactory renderEngineFactory, @NotNull RenderConfiguration renderConfiguration) { // Create the renderer + @NotNull Renderer renderer = new Renderer(renderConfiguration, renderEngineFactory); renderer.startRenderer(); return renderer; @@ -120,8 +133,10 @@ public Renderer getRenderer(RenderEngineFactory renderEngineFactory, RenderConfi * @return View resolver */ @Bean - public ViewResolver getViewResolver(Renderer renderer, RenderConfiguration renderConfiguration) { + @NotNull + public ViewResolver getViewResolver(@NotNull Renderer renderer, @NotNull RenderConfiguration renderConfiguration) { // Create the view resolver + @NotNull AngularJUniversalViewResolver viewResolver = new AngularJUniversalViewResolver(renderer, renderConfiguration); viewResolver.setOrder(0); return viewResolver; @@ -134,7 +149,8 @@ public ViewResolver getViewResolver(Renderer renderer, RenderConfiguration rende * @return Web MVC configurer with the application routes */ @Bean - public WebMvcConfigurer getWebMvcConfigurer(RenderConfiguration renderConfiguration) { + @NotNull + public WebMvcConfigurer getWebMvcConfigurer(@NotNull RenderConfiguration renderConfiguration) { return new AngularJUniversalConfigurer(renderConfiguration); } } diff --git a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalConfigurer.java b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalConfigurer.java index c2fc3d1..5a2e809 100644 --- a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalConfigurer.java +++ b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalConfigurer.java @@ -1,6 +1,7 @@ package ch.swaechter.angularjuniversal.springboot.starter; import ch.swaechter.angularjuniversal.renderer.configuration.RenderConfiguration; +import org.jetbrains.annotations.NotNull; import org.springframework.web.servlet.config.annotation.ViewControllerRegistration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -16,6 +17,7 @@ public class AngularJUniversalConfigurer implements WebMvcConfigurer { /** * Render configuration that will be used to check the routes. */ + @NotNull private final RenderConfiguration renderConfiguration; /** @@ -23,7 +25,7 @@ public class AngularJUniversalConfigurer implements WebMvcConfigurer { * * @param renderConfiguration Render configuration */ - public AngularJUniversalConfigurer(RenderConfiguration renderConfiguration) { + public AngularJUniversalConfigurer(@NotNull RenderConfiguration renderConfiguration) { this.renderConfiguration = renderConfiguration; } @@ -34,8 +36,9 @@ public AngularJUniversalConfigurer(RenderConfiguration renderConfiguration) { * @param viewControllerRegistry Registry to add new view controllers */ @Override - public void addViewControllers(ViewControllerRegistry viewControllerRegistry) { + public void addViewControllers(@NotNull ViewControllerRegistry viewControllerRegistry) { for (String url : renderConfiguration.getRoutes()) { + @NotNull ViewControllerRegistration viewControllerRegistration = viewControllerRegistry.addViewController(url); viewControllerRegistration.setViewName(url); } diff --git a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalProperties.java b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalProperties.java index 8a7f823..2d8671f 100644 --- a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalProperties.java +++ b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalProperties.java @@ -1,5 +1,6 @@ package ch.swaechter.angularjuniversal.springboot.starter; +import org.jetbrains.annotations.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; import java.nio.charset.Charset; @@ -18,31 +19,37 @@ public class AngularJUniversalProperties { /** * Path or executable name of the Node.js executable. This path is used to start a Node.js process for rendering. */ + @NotNull private String nodepath = "node"; /** * Port of the Node.js process is opening a TCP server. */ + @NotNull private Integer nodeport = 9090; /** * Path of the server bundle resource. */ + @NotNull private String serverbundleresourcepath = "/server.js"; /** * Path of the index resource. */ + @NotNull private String indexresourcepath = "/public/index.html"; /** * Charset used for reading and rendering. */ + @NotNull private Charset charset = StandardCharsets.UTF_8; /** * Comma separated list with all routes of the application. */ + @NotNull private List routes = Arrays.asList("/"); /** @@ -50,6 +57,7 @@ public class AngularJUniversalProperties { * * @return Node.js path or executable name */ + @NotNull public String getNodePath() { return nodepath; } @@ -59,7 +67,7 @@ public String getNodePath() { * * @param nodepath New Node.js path or executable name */ - public void setNodePath(String nodepath) { + public void setNodePath(@NotNull String nodepath) { this.nodepath = nodepath; } @@ -68,6 +76,7 @@ public void setNodePath(String nodepath) { * * @return Node.js port used for TCP communication */ + @NotNull public Integer getNodePort() { return nodeport; } @@ -77,7 +86,7 @@ public Integer getNodePort() { * * @param nodeport New Node.js port used for TCP communication */ - public void setNodePort(Integer nodeport) { + public void setNodePort(@NotNull Integer nodeport) { this.nodeport = nodeport; } @@ -86,6 +95,7 @@ public void setNodePort(Integer nodeport) { * * @return Path of the server bundle */ + @NotNull public String getServerBundleResourcePath() { return serverbundleresourcepath; } @@ -95,7 +105,7 @@ public String getServerBundleResourcePath() { * * @param serverbundleresourcepath Path of the new server bundle resource */ - public void setServerBundleResourcePath(String serverbundleresourcepath) { + public void setServerBundleResourcePath(@NotNull String serverbundleresourcepath) { this.serverbundleresourcepath = serverbundleresourcepath; } @@ -104,6 +114,7 @@ public void setServerBundleResourcePath(String serverbundleresourcepath) { * * @return Path of the index resource */ + @NotNull public String getIndexResourcePath() { return indexresourcepath; } @@ -113,7 +124,7 @@ public String getIndexResourcePath() { * * @param indexresourcepath Path of the new index resource */ - public void setIndexResourcePath(String indexresourcepath) { + public void setIndexResourcePath(@NotNull String indexresourcepath) { this.indexresourcepath = indexresourcepath; } @@ -122,6 +133,7 @@ public void setIndexResourcePath(String indexresourcepath) { * * @return Charset */ + @NotNull public Charset getCharset() { return charset; } @@ -131,7 +143,7 @@ public Charset getCharset() { * * @param charset New charset */ - public void setCharset(Charset charset) { + public void setCharset(@NotNull Charset charset) { this.charset = charset; } @@ -140,6 +152,7 @@ public void setCharset(Charset charset) { * * @return All routes as list */ + @NotNull public List getRoutes() { return routes; } @@ -149,7 +162,7 @@ public List getRoutes() { * * @param routes All routes as list */ - public void setRoutes(List routes) { + public void setRoutes(@NotNull List routes) { this.routes = routes; } } diff --git a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalUtils.java b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalUtils.java index c0ef242..7168ef3 100644 --- a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalUtils.java +++ b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalUtils.java @@ -1,5 +1,6 @@ package ch.swaechter.angularjuniversal.springboot.starter; +import org.jetbrains.annotations.NotNull; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; @@ -11,7 +12,10 @@ * * @author Simon Wächter */ -public class AngularJUniversalUtils { +public abstract class AngularJUniversalUtils { + + private AngularJUniversalUtils() { + } /** * Get the input stream from a resource. @@ -21,8 +25,8 @@ public class AngularJUniversalUtils { * @return Valid input stream or null * @throws IOException Exception in case of an IO problem */ - - public static InputStream getInputStreamFromResource(ResourceLoader resourceLoader, String resourceFilePath) throws IOException { + @NotNull + public static InputStream getInputStreamFromResource(@NotNull ResourceLoader resourceLoader, @NotNull String resourceFilePath) throws IOException { Resource resource = resourceLoader.getResource("classpath:" + resourceFilePath); return resource.getInputStream(); } diff --git a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalView.java b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalView.java index 7acaebf..97165e9 100644 --- a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalView.java +++ b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalView.java @@ -2,6 +2,7 @@ import ch.swaechter.angularjuniversal.renderer.Renderer; import ch.swaechter.angularjuniversal.renderer.configuration.RenderConfiguration; +import org.jetbrains.annotations.NotNull; import org.springframework.web.servlet.view.AbstractTemplateView; import javax.servlet.http.HttpServletRequest; @@ -14,11 +15,13 @@ public class AngularJUniversalView extends AbstractTemplateView { /** * Renderer for rendering page requests. */ + @NotNull private final Renderer renderer; /** * Render configuration that will be used to check the routes. */ + @NotNull private final RenderConfiguration renderConfiguration; /** @@ -27,7 +30,7 @@ public class AngularJUniversalView extends AbstractTemplateView { * @param renderer Renderer * @param renderConfiguration Render configuration */ - public AngularJUniversalView(Renderer renderer, RenderConfiguration renderConfiguration) { + public AngularJUniversalView(@NotNull Renderer renderer, @NotNull RenderConfiguration renderConfiguration) { this.renderer = renderer; this.renderConfiguration = renderConfiguration; } @@ -51,9 +54,10 @@ protected boolean isUrlRequired() { * @throws Exception Exception in case of a problem */ @Override - protected void renderMergedTemplateModel(Map map, HttpServletRequest request, HttpServletResponse response) throws Exception { + protected void renderMergedTemplateModel(@NotNull Map map, @NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws Exception { response.setCharacterEncoding(renderConfiguration.getCharset().name()); response.setContentType("text/html"); + @NotNull PrintWriter writer = response.getWriter(); writer.println(renderer.addRenderRequest(request.getRequestURI()).get()); writer.flush(); diff --git a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalViewResolver.java b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalViewResolver.java index e0dbdeb..3b0f921 100644 --- a/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalViewResolver.java +++ b/angularj-universal-spring-boot-starter/src/main/java/ch/swaechter/angularjuniversal/springboot/starter/AngularJUniversalViewResolver.java @@ -2,6 +2,7 @@ import ch.swaechter.angularjuniversal.renderer.Renderer; import ch.swaechter.angularjuniversal.renderer.configuration.RenderConfiguration; +import org.jetbrains.annotations.NotNull; import org.springframework.util.AntPathMatcher; import org.springframework.web.servlet.view.AbstractTemplateViewResolver; import org.springframework.web.servlet.view.AbstractUrlBasedView; @@ -18,11 +19,13 @@ public class AngularJUniversalViewResolver extends AbstractTemplateViewResolver /** * Renderer that will be passed to the view for rendering the page request. */ + @NotNull private final Renderer renderer; /** * Render configuration that will be used to check the routes. */ + @NotNull private final RenderConfiguration renderConfiguration; /** @@ -31,7 +34,7 @@ public class AngularJUniversalViewResolver extends AbstractTemplateViewResolver * @param renderer Renderer * @param renderConfiguration Render configuration */ - public AngularJUniversalViewResolver(Renderer renderer, RenderConfiguration renderConfiguration) { + public AngularJUniversalViewResolver(@NotNull Renderer renderer, @NotNull RenderConfiguration renderConfiguration) { setViewClass(requiredViewClass()); this.renderer = renderer; this.renderConfiguration = renderConfiguration; @@ -43,6 +46,7 @@ public AngularJUniversalViewResolver(Renderer renderer, RenderConfiguration rend * @return AngularJ Universal view class */ @Override + @NotNull public Class requiredViewClass() { return AngularJUniversalView.class; } @@ -56,7 +60,8 @@ public Class requiredViewClass() { * @return Status of the check */ @Override - public boolean canHandle(String modelName, Locale locale) { + public boolean canHandle(@NotNull String modelName, @NotNull Locale locale) { + @NotNull AntPathMatcher antPathMatcher = new AntPathMatcher(); for (String url : renderConfiguration.getRoutes()) { if (antPathMatcher.match(url, modelName)) { @@ -73,7 +78,8 @@ public boolean canHandle(String modelName, Locale locale) { * @return Valid view */ @Override - public AbstractUrlBasedView buildView(String uri) { + @NotNull + public AbstractUrlBasedView buildView(@NotNull String uri) { return new AngularJUniversalView(renderer, renderConfiguration); } } diff --git a/pom.xml b/pom.xml index e86cd7e..e93def5 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,12 @@ None https://github.com/swaechter + + Marcel Mundl + marcel@mundlhome.de + None + https://github.com/haringat + scm:git:git://github.com/swaechter/angularj-universal.git @@ -50,6 +56,13 @@ angularj-universal-example-spring-boot angularj-universal-example-spring-boot-simple + + + org.jetbrains + annotations + 17.0.0 + + @@ -57,7 +70,7 @@ maven-compiler-plugin 3.7.0 - 1.8 + 1.11 1.8 From 95250c368dfc2fec5171c9ca2d4285b3b43cd9b2 Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 24 May 2019 15:46:08 +0200 Subject: [PATCH 2/3] reverted source level back to 1.8 --- angularj-universal-example-spring-boot-simple/pom.xml | 2 +- angularj-universal-example-spring-boot/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/angularj-universal-example-spring-boot-simple/pom.xml b/angularj-universal-example-spring-boot-simple/pom.xml index 28dba57..2ffb19d 100644 --- a/angularj-universal-example-spring-boot-simple/pom.xml +++ b/angularj-universal-example-spring-boot-simple/pom.xml @@ -51,7 +51,7 @@ maven-compiler-plugin 3.7.0 - 1.11 + 1.8 1.8 diff --git a/angularj-universal-example-spring-boot/pom.xml b/angularj-universal-example-spring-boot/pom.xml index 7a53906..cee40a7 100644 --- a/angularj-universal-example-spring-boot/pom.xml +++ b/angularj-universal-example-spring-boot/pom.xml @@ -56,7 +56,7 @@ maven-compiler-plugin 3.7.0 - 1.11 + 1.8 1.8 diff --git a/pom.xml b/pom.xml index e93def5..f91ffeb 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ maven-compiler-plugin 3.7.0 - 1.11 + 1.8 1.8 From bd5057f79671da125dfd76ada613367185e7610a Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 24 May 2019 20:44:45 +0200 Subject: [PATCH 3/3] made the request/respones id a number according to the source code (https://github.com/angular/universal/blob/master/modules/socket-engine/src/main.ts line 18/22) --- .../tcprenderer/TcpRenderEngine.java | 2 +- .../angularjuniversal/tcprenderer/TcpRequest.java | 15 ++++++--------- .../tcprenderer/TcpResponse.java | 6 +++--- .../renderer/request/RenderRequest.java | 14 ++++++-------- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java index 1af03fc..e08d964 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRenderEngine.java @@ -80,7 +80,7 @@ public void startWorking(@NotNull BlockingQueue> renderR // Write the request @NotNull - TcpRequest tcpRequest = new TcpRequest(renderRequest.getUuid(), renderRequest.getUri(), renderConfiguration.getTemplateContent()); + TcpRequest tcpRequest = new TcpRequest(renderRequest.getId(), renderRequest.getUri(), renderConfiguration.getTemplateContent()); writer.println(objectMapper.writeValueAsString(tcpRequest)); writer.flush(); diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java index 2df04f3..c9a5b31 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpRequest.java @@ -15,27 +15,24 @@ public class TcpRequest { * ID of the render request. */ @NotNull - private String id; + private Long id = 0L; /** * URL of the render request. */ @NotNull - private String url; + private String url = ""; /** * Fallback document template. */ @NotNull - private String document; + private String document = ""; /** * Default constructor for Jackson */ public TcpRequest() { - this.id = UUID.randomUUID().toString(); - this.url = ""; - this.document = ""; } /** @@ -45,7 +42,7 @@ public TcpRequest() { * @param url URL of the render request * @param document Fallback document template */ - public TcpRequest(@NotNull String id, @NotNull String url, @NotNull String document) { + public TcpRequest(long id, @NotNull String url, @NotNull String document) { this.id = id; this.url = url; this.document = document; @@ -57,7 +54,7 @@ public TcpRequest(@NotNull String id, @NotNull String url, @NotNull String docum * @return ID of the request */ @NotNull - public String getId() { + public Long getId() { return id; } @@ -66,7 +63,7 @@ public String getId() { * * @param id New ID of the request */ - public void setId(@NotNull String id) { + public void setId(@NotNull Long id) { this.id = id; } diff --git a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java index 8d65cf4..a1e79c1 100644 --- a/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java +++ b/angularj-universal-renderer-tcp/src/main/java/ch/swaechter/angularjuniversal/tcprenderer/TcpResponse.java @@ -20,7 +20,7 @@ public class TcpResponse { * ID of the render response. */ @NotNull - private String id; + private Long id = 0L; /** * The error if one occurred @@ -59,7 +59,7 @@ public void setHtml(@Nullable String html) { * @return ID of the response */ @NotNull - public String getId() { + public Long getId() { return id; } @@ -68,7 +68,7 @@ public String getId() { * * @param id New ID of the response */ - public void setId(@NotNull String id) { + public void setId(@NotNull Long id) { this.id = id; } diff --git a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java index 60be6c2..dd24c72 100644 --- a/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java +++ b/angularj-universal-renderer/src/main/java/ch/swaechter/angularjuniversal/renderer/request/RenderRequest.java @@ -13,17 +13,18 @@ */ public class RenderRequest { + private static long lastId = 0L; + /** * Completable future that will contain the rendered content. */ @NotNull - private CompletableFuture future; + private CompletableFuture future = new CompletableFuture<>(); /** * Unique UUID of the request. */ - @NotNull - private String uuid; + private long id = ++RenderRequest.lastId; /** * URI of the request. @@ -37,8 +38,6 @@ public class RenderRequest { * @param uri URI of the page request */ public RenderRequest(@NotNull String uri) { - this.future = new CompletableFuture<>(); - this.uuid = UUID.randomUUID().toString(); this.uri = uri; } @@ -57,9 +56,8 @@ public CompletableFuture getFuture() { * * @return Unique UUID of the render request */ - @NotNull - public String getUuid() { - return uuid; + public long getId() { + return id; } /**