diff --git a/simpleexample2/fxui/build.gradle b/simpleexample2/fxui/build.gradle index 0132f1096faba03226037552a214c8c021f99b9d..649600ead9e196979bd7262c4b55d8b4cbcfbb00 100644 --- a/simpleexample2/fxui/build.gradle +++ b/simpleexample2/fxui/build.gradle @@ -65,6 +65,8 @@ dependencies { testImplementation 'junit:junit:4.12' // brukergrensesnitt + testImplementation project(':restserver') + testImplementation 'org.testfx:testfx-core:4.0.16-alpha' testImplementation 'org.testfx:testfx-junit:4.0.16-alpha' testImplementation 'org.mockito:mockito-core:2.28.2' diff --git a/simpleexample2/fxui/src/main/java/simpleex/ui/FxAppControllerUsingRest.java b/simpleexample2/fxui/src/main/java/simpleex/ui/FxAppUsingRestController.java similarity index 69% rename from simpleexample2/fxui/src/main/java/simpleex/ui/FxAppControllerUsingRest.java rename to simpleexample2/fxui/src/main/java/simpleex/ui/FxAppUsingRestController.java index acdc5b19e043ae11d6114aee67f758dac4cbf690..905bac6013c813bf176d3106550a73fc273792ad 100644 --- a/simpleexample2/fxui/src/main/java/simpleex/ui/FxAppControllerUsingRest.java +++ b/simpleexample2/fxui/src/main/java/simpleex/ui/FxAppUsingRestController.java @@ -22,9 +22,9 @@ FxAppController --> ListView: "locationListView" * @author hal * */ -public class FxAppControllerUsingRest extends AbstractFxAppController { +public class FxAppUsingRestController extends AbstractFxAppController { - public FxAppControllerUsingRest() { - setDataAccess(new RestLatLongsDataAccess(getObjectMapper())); + public FxAppUsingRestController() { + setDataAccess(new RestLatLongsDataAccess("http://localhost:8080/dict", getObjectMapper())); } } diff --git a/simpleexample2/fxui/src/main/java/simpleex/ui/RestLatLongsDataAccess.java b/simpleexample2/fxui/src/main/java/simpleex/ui/RestLatLongsDataAccess.java index 4a9b9ea436ca101ac5eb263c5ca93cc2ab0a53d9..1c31607bc5ee28d7cc91e713afa503b5e4f39058 100644 --- a/simpleexample2/fxui/src/main/java/simpleex/ui/RestLatLongsDataAccess.java +++ b/simpleexample2/fxui/src/main/java/simpleex/ui/RestLatLongsDataAccess.java @@ -41,11 +41,12 @@ FxAppController --> ListView: "locationListView" */ public class RestLatLongsDataAccess implements LatLongsDataAccess { - private String baseUrlString; + private final String baseUrlString; private final ObjectMapper objectMapper; - public RestLatLongsDataAccess(final ObjectMapper objectMapper) { + public RestLatLongsDataAccess(final String baseUrlString, final ObjectMapper objectMapper) { + this.baseUrlString = baseUrlString; this.objectMapper = objectMapper; } @@ -63,14 +64,18 @@ public class RestLatLongsDataAccess implements LatLongsDataAccess { @Override public Collection<LatLong> getAllLatLongs() { - final HttpRequest request = HttpRequest.newBuilder(getRequestUri("")) + final URI requestUri = getRequestUri(""); + final HttpRequest request = HttpRequest.newBuilder(requestUri) + .header("Accept", "application/json") .GET() .build(); try { - final HttpResponse<InputStream> response = HttpClient.newBuilder() + final HttpResponse<String> response = HttpClient.newBuilder() .build() - .send(request, HttpResponse.BodyHandlers.ofInputStream()); - return getObjectMapper().readValue(response.body(), LatLongs.class).toList(); + .send(request, HttpResponse.BodyHandlers.ofString()); + final String responseString = response.body(); + final LatLongs readValue = getObjectMapper().readValue(responseString, LatLongs.class); + return readValue.toList(); } catch (JsonParseException | JsonMappingException e) { } catch (IOException | InterruptedException e) { } @@ -80,6 +85,7 @@ public class RestLatLongsDataAccess implements LatLongsDataAccess { @Override public LatLong getLatLong(final int num) { final HttpRequest request = HttpRequest.newBuilder(getRequestUri("/" + num)) + .header("Accept", "application/json") .GET() .build(); try { @@ -97,6 +103,8 @@ public class RestLatLongsDataAccess implements LatLongsDataAccess { public void setLatLong(final int index, final LatLong latLong) { try { final HttpRequest request = HttpRequest.newBuilder(getRequestUri("/" + index)) + .header("Content-Type", "application/json") + .header("Accept", "application/json") .PUT(BodyPublishers.ofString(getObjectMapper().writeValueAsString(latLong))) .build(); final HttpResponse<InputStream> response = HttpClient.newBuilder() @@ -116,8 +124,11 @@ public class RestLatLongsDataAccess implements LatLongsDataAccess { @Override public int addLatLong(final LatLong latLong) { try { + final LatLongs latLongs = new LatLongs(latLong); final HttpRequest request = HttpRequest.newBuilder(getRequestUri("")) - .POST(BodyPublishers.ofString(getObjectMapper().writeValueAsString(latLong))) + .header("Content-Type", "application/json") + .header("Accept", "application/json") + .POST(BodyPublishers.ofString(getObjectMapper().writeValueAsString(latLongs))) .build(); final HttpResponse<InputStream> response = HttpClient.newBuilder() .build() diff --git a/simpleexample2/fxui/src/test/java/simpleex/ui/AbstractFxAppTest.java b/simpleexample2/fxui/src/test/java/simpleex/ui/AbstractFxAppTest.java index 50d163a2521a4986c39f10d5c87c28bc6a5b1f1e..1523c719fa0a8648ffaa0b87bb93fa235cb444ff 100644 --- a/simpleexample2/fxui/src/test/java/simpleex/ui/AbstractFxAppTest.java +++ b/simpleexample2/fxui/src/test/java/simpleex/ui/AbstractFxAppTest.java @@ -4,6 +4,7 @@ import static org.mockito.Mockito.verify; import fxmapcontrol.Location; import fxmapcontrol.MapBase; import java.net.URL; +import java.util.Collection; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -36,7 +37,7 @@ public abstract class AbstractFxAppTest extends ApplicationTest { } } - private AbstractFxAppController controller; + protected AbstractFxAppController controller; protected abstract URL getFxmlResource(); @@ -44,8 +45,8 @@ public abstract class AbstractFxAppTest extends ApplicationTest { public void start(final Stage stage) throws Exception { final FXMLLoader loader = new FXMLLoader(getFxmlResource()); final Parent root = loader.load(); - setUpLatLongsDataAccess(); this.controller = loader.getController(); + setUpLatLongsDataAccess(); this.controller.setDataAccess(getDataAccess()); final Scene scene = new Scene(root); stage.setScene(scene); @@ -64,7 +65,9 @@ public abstract class AbstractFxAppTest extends ApplicationTest { public void testLocationListView() { final ListView<?> locationListView = lookup("#locationListView").query(); // list contains equals elements in same order - Assert.assertEquals(getDataAccess().getAllLatLongs(), locationListView.getItems()); + final Collection<LatLong> allLatLongs = getDataAccess().getAllLatLongs(); + Assert.assertEquals(2, allLatLongs.size()); + Assert.assertEquals(allLatLongs, locationListView.getItems()); // first list element is auto-selected Assert.assertEquals(0, locationListView.getSelectionModel().getSelectedIndex()); } diff --git a/simpleexample2/fxui/src/test/java/simpleex/ui/FxAppUsingRestTest.java b/simpleexample2/fxui/src/test/java/simpleex/ui/FxAppUsingRestTest.java new file mode 100644 index 0000000000000000000000000000000000000000..893452e30a1532ef37dfe870f9f781dfd46c9c0c --- /dev/null +++ b/simpleexample2/fxui/src/test/java/simpleex/ui/FxAppUsingRestTest.java @@ -0,0 +1,51 @@ +package simpleex.ui; + +import java.io.IOException; +import java.net.URL; +import org.glassfish.grizzly.http.server.HttpServer; +import org.junit.After; +import simpleex.restapi.LatLongsService; +import simpleex.restserver.LatLongGrizzlyApp; + +public class FxAppUsingRestTest extends AbstractFxAppTest { + + @Override + protected URL getFxmlResource() { + return getClass().getResource("FxAppUsingRest.fxml"); + } + + private LatLongsDataAccess dataAccess; + + @Override + protected LatLongsDataAccess getDataAccess() { + return dataAccess; + } + + private HttpServer currentServer; + + @Override + protected void setUpLatLongsDataAccess() { + // "mocked" (faked) LatLongsDataAccess object with very specific and limited behavior + final String serverUrlString = "http://localhost:8080/"; + final String clientUrlString = serverUrlString + LatLongsService.LAT_LONG_SERVICE_PATH; + dataAccess = new RestLatLongsDataAccess(clientUrlString, controller.getObjectMapper()); + try { + currentServer = LatLongGrizzlyApp.startServer(new String[] { + serverUrlString, + "[[63.1, 11.2], [63.2, 11.0]]" + }); + // wait for server to start + int tryCount = 10; + while (tryCount-- > 0 && dataAccess.getAllLatLongs().isEmpty()) { + Thread.sleep(500); + } + } catch (final IOException | InterruptedException e) { + throw new IllegalStateException("Couldn't setup server"); + } + } + + @After + public void stopServer() { + currentServer.shutdownNow(); + } +} diff --git a/simpleexample2/restapi/build.gradle b/simpleexample2/restapi/build.gradle index 30d50424d187f4799287a0a5ed91b147ef59a42b..ee184042637b330a69e1c1e2706eeb1bf47e104c 100644 --- a/simpleexample2/restapi/build.gradle +++ b/simpleexample2/restapi/build.gradle @@ -2,6 +2,9 @@ plugins { id 'java-library' } +sourceCompatibility = JavaVersion.VERSION_1_10 +targetCompatibility = JavaVersion.VERSION_1_10 + dependencies { implementation project(':core') diff --git a/simpleexample2/restapi/src/main/java/simpleex/restapi/LatLongsService.java b/simpleexample2/restapi/src/main/java/simpleex/restapi/LatLongsService.java index 220a9e8a393a36070650c5286a7803f12ba76481..9fbec9c50d68c465fe8b001c589684668a55373e 100644 --- a/simpleexample2/restapi/src/main/java/simpleex/restapi/LatLongsService.java +++ b/simpleexample2/restapi/src/main/java/simpleex/restapi/LatLongsService.java @@ -38,13 +38,6 @@ public class LatLongsService { return latLongs.getLatLong(num); } - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public int addLatLong(final LatLong latLong) { - return this.latLongs.addLatLong(latLong); - } - @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) diff --git a/simpleexample2/restserver/build.gradle b/simpleexample2/restserver/build.gradle index 1ca5bba49cb80e54aa9e7b52f0571bc1bcac4029..c472e7c019a9cbbe04ce39c747f2da0868d79dce 100644 --- a/simpleexample2/restserver/build.gradle +++ b/simpleexample2/restserver/build.gradle @@ -7,7 +7,11 @@ ext { jerseyVersion = '2.28' } -mainClassName = 'multiex.jersey.LatLongGrizzlyApp' +application { + sourceCompatibility = JavaVersion.VERSION_1_10 + targetCompatibility = JavaVersion.VERSION_1_10 + mainClassName = 'simpleex.restserver.LatLongGrizzlyApp' +} dependencies { implementation project(':core') @@ -25,12 +29,12 @@ dependencies { // See https://jersey.github.io/documentation/latest/deployment.html#deployment.http for various server options compile "org.glassfish.jersey.containers:jersey-container-grizzly2-http:$jerseyVersion" - testImplementation "org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:$jerseyVersion" + implementation "org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:$jerseyVersion" - testRuntime 'javax.activation:activation:1.1.1' - testRuntime 'javax.xml.bind:jaxb-api:2.3.0' - testRuntime 'com.sun.xml.bind:jaxb-core:2.3.0' - testRuntime 'com.sun.xml.bind:jaxb-impl:2.3.0' + runtime 'javax.activation:activation:1.1.1' + runtime 'javax.xml.bind:jaxb-api:2.3.0' + runtime 'com.sun.xml.bind:jaxb-core:2.3.0' + runtime 'com.sun.xml.bind:jaxb-impl:2.3.0' } test { diff --git a/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongConfig.java b/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongConfig.java index 173d5fcc7885b65a18341cb25f1ed3f1550e432d..ccf70cd5f02a054d1c789665653a08284b7c72d7 100644 --- a/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongConfig.java +++ b/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongConfig.java @@ -1,5 +1,7 @@ package simpleex.restserver; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; import org.glassfish.hk2.utilities.binding.AbstractBinder; import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.server.ResourceConfig; @@ -9,14 +11,27 @@ import simpleex.restapi.LatLongsService; public class LatLongConfig extends ResourceConfig { - final LatLongs latLongs; - public LatLongConfig() { this(new LatLongs()); } + private static LatLongs readValue(final String json) { + try { + final LatLongs latLongs = new LatLongObjectMapperProvider().getContext(ObjectMapper.class).readValue(json, LatLongs.class); + System.out.println("Read " + json + " as " + latLongs); + return latLongs; + } catch (final Exception e) { + System.out.println("Exception when reading " + json + ": " + e); + } + return null; + } + + public LatLongConfig(final String json) throws IOException { + this(readValue(json)); + } + public LatLongConfig(final LatLongs latLongs) { - this.latLongs = latLongs; + System.out.println("Serving " + latLongs.toList()); register(LatLongsService.class); register(LatLongObjectMapperProvider.class); register(JacksonFeature.class); diff --git a/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongGrizzlyApp.java b/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongGrizzlyApp.java index dc0faf74ba96087d81a2cb654e95cb2fa2c0989b..e6c14a237f02728e29525de6461505a9ef8adb66 100644 --- a/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongGrizzlyApp.java +++ b/simpleexample2/restserver/src/main/java/simpleex/restserver/LatLongGrizzlyApp.java @@ -1,5 +1,6 @@ package simpleex.restserver; +import java.io.IOException; import java.net.URI; import java.util.logging.Level; import java.util.logging.Logger; @@ -9,16 +10,25 @@ import org.glassfish.jersey.server.ResourceConfig; public class LatLongGrizzlyApp { - private static final URI BASE_URI = URI.create("http://localhost:8080/"); + private static URI BASE_URI = URI.create("http://localhost:8080/"); - public static void main(final String[] args) { - try { - final ResourceConfig resourceConfig = new LatLongConfig(); - final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, resourceConfig); - Runtime.getRuntime().addShutdownHook(new Thread(server::shutdownNow)); - Thread.currentThread().join(); - } catch (final InterruptedException ex) { - Logger.getLogger(LatLongGrizzlyApp.class.getName()).log(Level.SEVERE, null, ex); - } - } + public static HttpServer startServer(final String[] args) throws IOException { + final URI baseUri = (args.length >= 1 ? URI.create(args[0]) : BASE_URI); + final ResourceConfig resourceConfig = (args.length >= 2 ? new LatLongConfig(args[1]) : new LatLongConfig()); + return GrizzlyHttpServerFactory.createHttpServer(baseUri, resourceConfig); + } + + public static void stopServer(final HttpServer server) throws IOException { + server.shutdown(); + } + + public static void main(final String[] args) throws IOException { + try { + final HttpServer server = startServer(args); + Runtime.getRuntime().addShutdownHook(new Thread(server::shutdownNow)); + Thread.currentThread().join(); + } catch (final InterruptedException ex) { + Logger.getLogger(LatLongGrizzlyApp.class.getName()).log(Level.SEVERE, null, ex); + } + } }