This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v4
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/v4 by this push:
new 94ce09459dd CAUSEWAY-3897: more migrating RestfulClient to Spring's
RestClient (RO)
94ce09459dd is described below
commit 94ce09459ddb64f6a493acbceb0d249d22c24104
Author: Andi Huber <[email protected]>
AuthorDate: Tue Jul 8 21:41:32 2025 +0200
CAUSEWAY-3897: more migrating RestfulClient to Spring's RestClient (RO)
---
.../causeway/applib/client/SuppressionType.java | 17 +-
.../applib/jaxb/PersistentEntityAdapter.java | 8 +-
regressiontests/base-jpa/pom.xml | 7 +-
.../jpa/rest/JpaRestEndpointService.java | 310 +++++++++++----------
regressiontests/rest-jpa/pom.xml | 11 -
.../testdomain/rest/jpa/RestServiceStressTest.java | 23 +-
.../testdomain/rest/jpa/RestServiceTest.java | 48 ++--
.../applib/src/main/java/module-info.java | 2 +-
.../applib/client/ActionParameterModel.java | 1 +
.../applib/client/CausewayMediaTypes.java | 79 ++++++
.../client/ActionParameterModelRecord.java | 214 --------------
viewers/restfulobjects/test/pom.xml | 24 --
...sewayViewerRestfulObjectsIntegTestAbstract.java | 17 --
.../test/scenarios/Abstract_IntegTest.java | 6 -
...Photo.DEPARTMENT_BOOKMARK_AS_MAP.approved.json} | 0
...oto.DEPARTMENT_BOOKMARK_AS_VALUE.approved.json} | 0
...rWithPhoto.DEPARTMENT_KEY_AS_MAP.approved.json} | 0
...ithPhoto.DEPARTMENT_KEY_AS_VALUE.approved.json} | 0
...hilevel_IntegTest.java => Staff_IntegTest.java} | 4 +-
...gTest.createStaffMemberWithPhoto2.approved.json | 13 -
.../staff/Staff_lowlevel_v1_IntegTest.java | 251 -----------------
...gTest.createStaffMemberWithPhoto2.approved.json | 17 --
.../staff/Staff_lowlevel_v2_IntegTest.java | 155 -----------
23 files changed, 295 insertions(+), 912 deletions(-)
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/client/SuppressionType.java
b/api/applib/src/main/java/org/apache/causeway/applib/client/SuppressionType.java
index 889ded6a976..267e4d306d8 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/client/SuppressionType.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/client/SuppressionType.java
@@ -20,8 +20,13 @@
import java.util.EnumSet;
import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.jspecify.annotations.Nullable;
import org.apache.causeway.commons.internal.base._NullSafe;
+import org.apache.causeway.commons.internal.base._Strings;
import static org.apache.causeway.commons.internal.base._NullSafe.stream;
@@ -58,11 +63,9 @@ public enum SuppressionType {
/**
* suppress all '$$...' entries
*/
- ALL
-
- ;
+ ALL;
- public static EnumSet<SuppressionType> all() { return EnumSet.of(ALL); };
+ public static EnumSet<SuppressionType> all() { return EnumSet.of(ALL); }
public static EnumSet<SuppressionType> setOf(final SuppressionType ...
types){
final EnumSet<SuppressionType> set =
EnumSet.noneOf(SuppressionType.class);
@@ -70,6 +73,12 @@ public static EnumSet<SuppressionType> setOf(final
SuppressionType ... types){
return set;
}
+ public static Optional<String> toLiteral(final @Nullable
EnumSet<SuppressionType> suppressionTypes) {
+ return _Strings.nonEmpty(_NullSafe.stream(suppressionTypes)
+ .map(SuppressionType::name)
+ .collect(Collectors.joining(",")));
+ }
+
public static class ParseUtil {
public static EnumSet<SuppressionType> parse(final List<String>
parameterList) {
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/jaxb/PersistentEntityAdapter.java
b/api/applib/src/main/java/org/apache/causeway/applib/jaxb/PersistentEntityAdapter.java
index 1d67512f67d..f087a3e1645 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/jaxb/PersistentEntityAdapter.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/jaxb/PersistentEntityAdapter.java
@@ -32,15 +32,17 @@ public class PersistentEntityAdapter extends
XmlAdapter<OidDto, Object> {
@Override
public Object unmarshal(final OidDto oidDto) throws Exception {
+ if(bookmarkService==null) return null;
+
var bookmark = Bookmark.forOidDto(oidDto);
return bookmarkService.lookup(bookmark).orElse(null);
}
@Override
public OidDto marshal(final Object domainObject) throws Exception {
- if(domainObject == null) {
- return null;
- }
+ if(domainObject == null) return null;
+ if(bookmarkService==null) return null;
+
var bookmark = bookmarkService.bookmarkForElseFail(domainObject);
return bookmark.toOidDto();
}
diff --git a/regressiontests/base-jpa/pom.xml b/regressiontests/base-jpa/pom.xml
index ed8b478bc87..a6a10a6d095 100644
--- a/regressiontests/base-jpa/pom.xml
+++ b/regressiontests/base-jpa/pom.xml
@@ -63,7 +63,7 @@
<dependency>
<groupId>org.apache.causeway.viewer</groupId>
- <artifactId>causeway-viewer-restfulobjects-client</artifactId>
+ <artifactId>causeway-viewer-restfulobjects-applib</artifactId>
</dependency>
<dependency>
@@ -72,11 +72,6 @@
<type>pom</type>
<optional>true</optional>
</dependency>
-<!-- <dependency>-->
-<!-- <groupId>org.apache.causeway.viewer</groupId>-->
-<!--
<artifactId>causeway-viewer-restfulobjects-jaxrsresteasy</artifactId>-->
-<!-- <optional>true</optional>-->
-<!-- </dependency>-->
<dependency>
<groupId>org.apache.causeway.viewer</groupId>
<artifactId>causeway-viewer-wicket-viewer</artifactId>
diff --git
a/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/rest/JpaRestEndpointService.java
b/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/rest/JpaRestEndpointService.java
index 430b974a4ee..c3784a15de7 100644
---
a/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/rest/JpaRestEndpointService.java
+++
b/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/rest/JpaRestEndpointService.java
@@ -18,39 +18,55 @@
*/
package org.apache.causeway.testdomain.jpa.rest;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.List;
-
import jakarta.inject.Inject;
-import jakarta.ws.rs.client.Invocation;
-import jakarta.ws.rs.core.GenericType;
import jakarta.xml.bind.JAXBException;
-import org.jspecify.annotations.NonNull;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+
+import org.jspecify.annotations.Nullable;
+import org.slf4j.Logger;
+import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
+import org.springframework.http.HttpInputMessage;
+import org.springframework.http.HttpOutputMessage;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.client.RestClient.Builder;
+import org.springframework.web.client.RestClient.RequestBodySpec;
+import org.springframework.web.client.RestClient.RequestBodyUriSpec;
-import org.apache.causeway.applib.client.SuppressionType;
import org.apache.causeway.applib.services.iactnlayer.InteractionService;
+import org.apache.causeway.applib.value.semantics.ValueDecomposition;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.functional.Try;
+import org.apache.causeway.commons.internal.base._Bytes;
+import org.apache.causeway.commons.io.JsonUtils;
import org.apache.causeway.core.config.CausewayConfiguration;
import org.apache.causeway.core.config.applib.RestfulPathProvider;
import org.apache.causeway.core.config.viewer.web.WebAppContextPath;
import org.apache.causeway.extensions.fullcalendar.applib.value.CalendarEvent;
import
org.apache.causeway.extensions.fullcalendar.applib.value.CalendarEventSemantics;
+import org.apache.causeway.schema.common.v2.ValueType;
import org.apache.causeway.testdomain.jpa.JpaInventoryJaxbVm;
import org.apache.causeway.testdomain.jpa.JpaTestFixtures;
import org.apache.causeway.testdomain.jpa.entities.JpaBook;
import org.apache.causeway.testdomain.ldap.LdapConstants;
import org.apache.causeway.testdomain.util.dto.BookDto;
-import org.apache.causeway.viewer.restfulobjects.client.AuthenticationMode;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClient;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClientConfig;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClientMediaType;
-import
org.apache.causeway.viewer.restfulobjects.client.log.ClientConversationFilter;
+import
org.apache.causeway.viewer.restfulobjects.applib.client.ActionParameterModel;
+import
org.apache.causeway.viewer.restfulobjects.applib.client.CausewayMediaTypes;
+import
org.apache.causeway.viewer.restfulobjects.applib.client.ConversationLogger;
+import lombok.Getter;
import lombok.RequiredArgsConstructor;
+import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
@Service
@@ -75,191 +91,195 @@ public int getPort() {
// -- NEW CLIENT
- public RestfulClient newClient(final boolean useRequestDebugLogging) {
- return newClient(useRequestDebugLogging, Can.empty());
- }
+ @Getter(lazy = true) @Accessors(fluent=true)
+ private final String baseUrl = "http://0.0.0.0:%d%s/".formatted(getPort(),
webAppContextPath
+ .prependContextPath(new
RestfulPathProvider(causewayConfiguration).getRestfulPath().orElse("")));
- public RestfulClient newClient(
- final boolean useRequestDebugLogging,
- final @NonNull Can<ClientConversationFilter> additionalFilters) {
-
- var restfulPathProvider = new
RestfulPathProvider(causewayConfiguration);
-
- var restRootPath =
- String.format("http://localhost:%d%s/",
- getPort(),
- webAppContextPath
-
.prependContextPath(restfulPathProvider.getRestfulPath().orElse(""))
- );
-
- log.debug("new restful client created for {}", restRootPath);
-
- var clientConfig = RestfulClientConfig.builder()
- .restfulBaseUrl(restRootPath)
- // setup basic-auth
- .authenticationMode(AuthenticationMode.BASIC)
- .basicAuthUser(LdapConstants.SVEN_PRINCIPAL)
- .basicAuthPassword("pass")
- // setup request/response debug logging
- .useRequestDebugLogging(useRequestDebugLogging)
- // register additional filter if any
- .clientConversationFilters(additionalFilters.toList())
- .build();
-
- var client = RestfulClient.ofConfig(clientConfig);
- return client;
+ record ValueHolder(String type, Object value) {
+ ValueDecomposition parseValueDecomposition() {
+ return ValueDecomposition.destringify(ValueType.COMPOSITE,
(String)value);
+ }
+ @SuppressWarnings("unchecked")
+ <T> T value(final Class<T> requiredType){
+ return (T) value;
+ }
}
+ record CausewayMessageConverter() implements HttpMessageConverter<Object> {
- // -- NEW REQUEST BUILDER
+ @Override
+ public boolean canRead(final Class<?> clazz, @Nullable final MediaType
mediaType) {
+ return clazz.equals(ValueDecomposition.class);
+ }
- public Invocation.Builder newInvocationBuilder(final RestfulClient client,
final String endpointPath) {
- var accept =
RestfulClientMediaType.SIMPLE_JSON.mediaTypeFor(Object.class,
SuppressionType.all()).toString();
- return client.request(endpointPath)
- .accept(accept);
- }
+ @Override
+ public boolean canWrite(final Class<?> clazz, @Nullable final
MediaType mediaType) {
+ return false;
+ }
- // -- ENDPOINTS
+ @Override
+ public List<MediaType> getSupportedMediaTypes() {
+ return List.of(MediaType.APPLICATION_JSON);
+ }
- public Try<JpaBook> getRecommendedBookOfTheWeek(final RestfulClient
client) {
+ @Override
+ public Object read(final Class<? extends Object> clazz, final
HttpInputMessage inputMessage)
+ throws IOException, HttpMessageNotReadableException {
+ var bytes = _Bytes.of(inputMessage.getBody());
+ var json = new String(bytes, StandardCharsets.UTF_8);
+ var valueHolder = JsonUtils.tryRead(ValueHolder.class, json)
+ .valueAsNonNullElseFail();
+ return ValueDecomposition.destringify(ValueType.COMPOSITE,
valueHolder.value(String.class));
+ }
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE +
"/actions/recommendedBookOfTheWeek/invoke");
- var args = client.arguments()
- .build();
+ @Override
+ public void write(final Object t, @Nullable final MediaType
contentType, final HttpOutputMessage outputMessage)
+ throws IOException, HttpMessageNotWritableException {
+ // TODO Auto-generated method stub
- var response = request.post(args);
- var digest = client.digest(response, JpaBook.class);
+ }
- return digest;
}
- public Try<BookDto> getRecommendedBookOfTheWeekDto(final RestfulClient
client) {
+ protected Builder restClient() {
+ return RestClient.builder()
+ .messageConverters(converters->converters.add(0, new
CausewayMessageConverter()))
+ .baseUrl(baseUrl())
+ .defaultHeaders(headers ->
headers.setBasicAuth(LdapConstants.SVEN_PRINCIPAL, "pass"));
+ }
+ protected Builder restClient(final Logger logger) {
+ return restClient()
+ .bufferContent((uri, method)->true)
+ .requestInterceptor(new ConversationLogger(msg->logger.info(msg)));
+ }
+ protected ActionParameterModel actParamModel() {
+ return ActionParameterModel.create(baseUrl());
+ }
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE +
"/actions/recommendedBookOfTheWeekDto/invoke");
- var args = client.arguments()
- .build();
+ public RestClient newClient(final boolean useRequestDebugLogging) {
+ log.debug("new restful client created for {}", baseUrl());
+ return useRequestDebugLogging
+ ? restClient(log).build()
+ : restClient().build();
+ }
- var response = request.post(args);
- var digest = client.digest(response, BookDto.class);
+ // -- NEW REQUEST BUILDER
- return digest;
+ public RequestBodySpec request(final RequestBodyUriSpec
requestBodyUriSpec, final String uri,
+ final ActionParameterModel actParamModel) {
+ return requestBodyUriSpec
+ .uri(INVENTORY_RESOURCE + uri)
+ .accept(CausewayMediaTypes.CAUSEWAY_JSON_V2_LIGHT)
+ .body(actParamModel.toJson());
}
- public Try<Can<JpaBook>> getMultipleBooks(final RestfulClient client)
throws JAXBException {
+ // -- ENDPOINTS
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE + "/actions/multipleBooks/invoke");
- var args = client.arguments()
- .addActionParameter("nrOfBooks", 3)
- .build();
+ public Try<JpaBook> getRecommendedBookOfTheWeek(final RestClient client) {
- var response = request.post(args);
- var digest = client.digestList(response, JpaBook.class, new
GenericType<List<JpaBook>>() {});
+ var response = request(client.post(),
"/actions/recommendedBookOfTheWeek/invoke", actParamModel())
+ .retrieve();
- return digest;
+ var entity = response.body(JpaBook.class);
+ return Try.success(entity);
}
- public Try<JpaBook> storeBook(final RestfulClient client, final JpaBook
newBook) throws JAXBException {
-
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE + "/actions/storeBook/invoke");
- var args = client.arguments()
- .addActionParameter("newBook", BookDto.from(newBook).encode())
- .build();
-
- var response = request.post(args);
- var digest = client.digest(response, JpaBook.class);
+ public Try<BookDto> getRecommendedBookOfTheWeekDto(final RestClient
client) {
+ var response = request(client.post(),
"/actions/recommendedBookOfTheWeekDto/invoke", actParamModel())
+ .retrieve();
- return digest;
+ var entity = response.body(BookDto.class);
+ return Try.success(entity);
}
- public Try<BookDto> getRecommendedBookOfTheWeekAsDto(final RestfulClient
client) {
+ public Try<Can<JpaBook>> getMultipleBooks(final RestClient client) throws
JAXBException {
+ var response = request(client.post(),"/actions/multipleBooks/invoke",
actParamModel()
+ .addActionParameter("nrOfBooks", 3))
+ .retrieve();
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE +
"/actions/recommendedBookOfTheWeekAsDto/invoke");
- var args = client.arguments()
- .build();
+ List<JpaBook> books = response
+ .body(new ParameterizedTypeReference<List<JpaBook>>() {});
- var response = request.post(args);
- var digest = client.digest(response, BookDto.class);
-
- return digest;
+ return Try.success(Can.ofCollection(books));
}
- public Try<Can<BookDto>> getMultipleBooksAsDto(final RestfulClient client)
throws JAXBException {
+ public Try<JpaBook> storeBook(final RestClient client, final JpaBook
newBook) throws JAXBException {
+ var response = request(client.post(), "/actions/storeBook/invoke",
actParamModel()
+ .addActionParameter("newBook", BookDto.from(newBook).encode()))
+ .retrieve();
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE + "/actions/multipleBooksAsDto/invoke");
- var args = client.arguments()
- .addActionParameter("nrOfBooks", 2)
- .build();
+ var entity = response.body(JpaBook.class);
+ return Try.success(entity);
+ }
- var response = request.post(args);
- var digest = client.digestList(response, BookDto.class, new
GenericType<List<BookDto>>() {});
+ public Try<BookDto> getRecommendedBookOfTheWeekAsDto(final RestClient
client) {
+ var response = request(client.post(),
"/actions/recommendedBookOfTheWeekAsDto/invoke", actParamModel())
+ .retrieve();
- return digest;
+ var entity = response.body(BookDto.class);
+ return Try.success(entity);
}
- public Try<JpaInventoryJaxbVm> getInventoryAsJaxbVm(final RestfulClient
client) {
+ public Try<Can<BookDto>> getMultipleBooksAsDto(final RestClient client)
throws JAXBException {
+ var response = request(client.post(),
"/actions/multipleBooksAsDto/invoke", actParamModel()
+ .addActionParameter("nrOfBooks", 2))
+ .retrieve();
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE + "/actions/inventoryAsJaxbVm/invoke");
- var args = client.arguments()
- .build();
+ List<BookDto> books = response
+ .body(new ParameterizedTypeReference<List<BookDto>>() {});
- var response = request.post(args);
- var digest = client.digest(response, JpaInventoryJaxbVm.class);
- return digest;
+ return Try.success(Can.ofCollection(books));
}
- public Try<Can<JpaBook>> getBooksFromInventoryAsJaxbVm(final RestfulClient
client) {
+ public Try<JpaInventoryJaxbVm> getInventoryAsJaxbVm(final RestClient
client) {
+ var response = request(client.post(),
"/actions/inventoryAsJaxbVm/invoke", actParamModel())
+ .retrieve();
+
+ return JsonUtils.tryRead(JpaInventoryJaxbVm.class,
response.body(String.class),
+ JsonUtils::jaxbAnnotationSupport,
+ m->m.disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES),
+ m->m.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
+ //var entity = response.body(JpaInventoryJaxbVm.class);
+ //return Try.success(entity);
+ }
+ public Try<Can<JpaBook>> getBooksFromInventoryAsJaxbVm(final RestClient
client) {
var objectId = interactionService.callAnonymous(
()->jpaTestFixtures.getInventoryJaxbVmAsBookmark().identifier());
// using domain object alias ...
- var request = newInvocationBuilder(client,
- "objects/testdomain.jpa.JpaInventoryJaxbVmAlias/"
- + objectId + "/actions/listBooks/invoke");
-
- var args = client.arguments()
- .build();
-
- var response = request.post(args);
- var digest = client.digestList(response, JpaBook.class, new
GenericType<List<JpaBook>>() {});
-
- return digest;
+ var response = client
+ .post()
+
.uri("objects/testdomain.jpa.JpaInventoryJaxbVmAlias/%s/actions/listBooks/invoke"
+ .formatted(objectId))
+ .accept(CausewayMediaTypes.CAUSEWAY_JSON_V2_LIGHT)
+ .body(actParamModel().toJson())
+ .retrieve();
+
+ List<JpaBook> books = response
+ .body(new ParameterizedTypeReference<List<JpaBook>>() {});
+
+ return Try.success(Can.ofCollection(books));
}
public Try<CalendarEvent> echoCalendarEvent(
- final RestfulClient client, final CalendarEvent calendarEvent) {
-
+ final RestClient client, final CalendarEvent calendarEvent) {
var calSemantics = new CalendarEventSemantics();
+ var response =
request(client.post(),"/actions/echoCalendarEvent/invoke", actParamModel()
+ .addActionParameter("calendarEvent",
calSemantics.decompose(calendarEvent)))
+ .retrieve();
+ var entity = response.body(ValueDecomposition.class);
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE + "/actions/echoCalendarEvent/invoke");
- var args = client.arguments()
- .addActionParameter("calendarEvent",
calSemantics.decompose(calendarEvent))
- .build();
-
- var response = request.post(args);
- var digest = client.digestValue(response, calSemantics);
-
- return digest;
+ var calendarEventEcho = calSemantics.compose(entity);
+ return Try.success(calendarEventEcho);
}
- public Try<String> getHttpSessionInfo(final RestfulClient client) {
-
- var request = newInvocationBuilder(client,
- INVENTORY_RESOURCE + "/actions/httpSessionInfo/invoke");
- var args = client.arguments()
- .build();
-
- var response = request.post(args);
- var digest = client.digest(response, String.class);
+ public Try<String> getHttpSessionInfo(final RestClient client) {
+ var args = actParamModel();
+ var response = request(client.post(),
"/actions/httpSessionInfo/invoke", args)
+ .retrieve();
- return digest;
+ var entity = response.body(ValueHolder.class);
+ return Try.success((String)entity.value());
}
// -- HELPER
diff --git a/regressiontests/rest-jpa/pom.xml b/regressiontests/rest-jpa/pom.xml
index 389463f6bf1..5ab1fe8b5df 100644
--- a/regressiontests/rest-jpa/pom.xml
+++ b/regressiontests/rest-jpa/pom.xml
@@ -57,22 +57,11 @@
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.apache.causeway.viewer</groupId>
-
<artifactId>causeway-viewer-restfulobjects-client</artifactId>
- <scope>test</scope>
- </dependency>
-
<dependency>
<groupId>org.apache.causeway.mavendeps</groupId>
<artifactId>causeway-mavendeps-webapp</artifactId>
<type>pom</type>
</dependency>
-<!-- <dependency>-->
-<!-- <groupId>org.apache.causeway.viewer</groupId>-->
-<!--
<artifactId>causeway-viewer-restfulobjects-jaxrsresteasy</artifactId>-->
-<!-- <scope>test</scope>-->
-<!-- </dependency>-->
<dependency>
<groupId>org.apache.causeway.extensions</groupId>
diff --git
a/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceStressTest.java
b/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceStressTest.java
index e59d12e4dd6..6ca2cc89635 100644
---
a/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceStressTest.java
+++
b/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceStressTest.java
@@ -22,7 +22,6 @@
import jakarta.inject.Inject;
-import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -32,12 +31,12 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.test.LocalServerPort;
import org.springframework.context.annotation.Import;
+import org.springframework.web.client.RestClient;
import org.apache.causeway.commons.internal.base._Timing;
import org.apache.causeway.testdomain.jpa.conf.Configuration_usingJpa;
import org.apache.causeway.testdomain.jpa.rest.JpaRestEndpointService;
import
org.apache.causeway.testing.unittestsupport.applib.annotations.DisabledIfRunningWithSurefire;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClient;
import
org.apache.causeway.viewer.restfulobjects.viewer.CausewayModuleViewerRestfulObjectsViewer;
import lombok.extern.slf4j.Slf4j;
@@ -80,17 +79,12 @@ void bookOfTheWeek_stressTest() {
IntStream.range(0, clients)
//.parallel()
- .mapToObj(i->{
- var restfulClient =
restService.newClient(USE_REQUEST_DEBUG_LOGGING);
- return restfulClient;
- })
- .forEach(restfulClient->{
-
+ .mapToObj(i->restService.newClient(USE_REQUEST_DEBUG_LOGGING))
+ .forEach(restClient->{
IntStream.range(0, iterations)
.forEach(iter->{
- requestSingleBookOfTheWeek_viaRestEndpoint(restfulClient);
+ requestSingleBookOfTheWeek_viaRestEndpoint(restClient);
});
-
});
});
@@ -99,12 +93,9 @@ void bookOfTheWeek_stressTest() {
}
- void requestSingleBookOfTheWeek_viaRestEndpoint(final RestfulClient
_restfulClient) {
- var restfulClient = restService.newClient(USE_REQUEST_DEBUG_LOGGING);
- var digest =
restService.getRecommendedBookOfTheWeekAsDto(restfulClient)
- .ifFailure(Assertions::fail);
-
- var bookOfTheWeek = digest.getValue().orElseThrow();
+ void requestSingleBookOfTheWeek_viaRestEndpoint(final RestClient
restClient) {
+ var bookOfTheWeek =
restService.getRecommendedBookOfTheWeekAsDto(restClient)
+ .valueAsNonNullElseFail();
assertNotNull(bookOfTheWeek);
assertEquals("Book of the week", bookOfTheWeek.getName());
diff --git
a/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceTest.java
b/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceTest.java
index 383b3ab9279..8cc7849c0fd 100644
---
a/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceTest.java
+++
b/regressiontests/rest-jpa/src/test/java/org/apache/causeway/testdomain/rest/jpa/RestServiceTest.java
@@ -35,6 +35,7 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.test.LocalServerPort;
import org.springframework.context.annotation.Import;
+import org.springframework.web.client.RestClient;
import
org.apache.causeway.extensions.fullcalendar.applib.value.CalendarEventSemantics;
import org.apache.causeway.testdomain.jpa.JpaInventoryJaxbVm;
@@ -43,7 +44,6 @@
import org.apache.causeway.testdomain.jpa.conf.Configuration_usingJpa;
import org.apache.causeway.testdomain.jpa.entities.JpaBook;
import org.apache.causeway.testdomain.jpa.rest.JpaRestEndpointService;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClient;
import
org.apache.causeway.viewer.restfulobjects.viewer.CausewayModuleViewerRestfulObjectsViewer;
@SpringBootTest(
@@ -66,22 +66,18 @@ class RestServiceTest extends RegressionTestWithJpaFixtures
{
@LocalServerPort int port; // just for reference (not used)
@Inject JpaRestEndpointService restService;
- private RestfulClient restfulClient;
+ private RestClient restClient;
@BeforeEach
void checkPrereq() {
assertTrue(restService.getPort()>0);
- this.restfulClient = restService.newClient(USE_REQUEST_DEBUG_LOGGING);
+ this.restClient = restService.newClient(USE_REQUEST_DEBUG_LOGGING);
}
@Test @Order(1)
void httpSessionInfo() {
- var digest = restService.getHttpSessionInfo(restfulClient)
- .ifFailureFail();
-
- var httpSessionInfo = digest.getValue().orElseThrow();
-
- assertNotNull(httpSessionInfo);
+ var httpSessionInfo = restService.getHttpSessionInfo(restClient)
+ .valueAsNonNullElseFail();
// NB: this works only because we excluded wicket viewer from the app.
assertEquals("no http-session", httpSessionInfo);
@@ -89,10 +85,10 @@ void httpSessionInfo() {
@Test @Order(2)
void bookOfTheWeek_viaRestEndpoint() {
- var digest = restService.getRecommendedBookOfTheWeek(restfulClient)
+ var entity = restService.getRecommendedBookOfTheWeek(restClient)
.ifFailureFail();
- var bookOfTheWeek = digest.getValue().orElseThrow();
+ var bookOfTheWeek = entity.valueAsNonNullElseFail();
assertNotNull(bookOfTheWeek);
assertEquals("Book of the week", bookOfTheWeek.getName());
@@ -103,10 +99,10 @@ void addNewBook_viaRestEndpoint() throws JAXBException {
var newBook = JpaBook.of("REST Book", "A sample REST book for
testing.", 77.,
"REST Author", "REST ISBN", "REST Publisher");
- var digest = restService.storeBook(restfulClient, newBook)
+ var entity = restService.storeBook(restClient, newBook)
.ifFailureFail();
- var storedBook = digest.getValue().orElseThrow();
+ var storedBook = entity.valueAsNonNullElseFail();
assertNotNull(storedBook);
assertEquals("REST Book", storedBook.getName());
@@ -114,12 +110,12 @@ void addNewBook_viaRestEndpoint() throws JAXBException {
@Test @Order(4)
void multipleBooks_viaRestEndpoint() throws JAXBException {
- var digest = restService.getMultipleBooks(restfulClient)
+ var entity = restService.getMultipleBooks(restClient)
.ifFailureFail();
var expectedBookTitles = JpaTestFixtures.expectedBookTitles();
- var multipleBooks = digest.getValue().orElseThrow()
+ var multipleBooks = entity.valueAsNonNullElseFail()
.filter(book->expectedBookTitles.contains(book.getName()));
assertEquals(3, multipleBooks.size());
@@ -127,10 +123,10 @@ void multipleBooks_viaRestEndpoint() throws JAXBException
{
@Test @Order(5)
void bookOfTheWeek_asDto_viaRestEndpoint() {
- var digest =
restService.getRecommendedBookOfTheWeekAsDto(restfulClient)
+ var entity = restService.getRecommendedBookOfTheWeekAsDto(restClient)
.ifFailureFail();
- var bookOfTheWeek = digest.getValue().orElseThrow();
+ var bookOfTheWeek = entity.valueAsNonNullElseFail();
assertNotNull(bookOfTheWeek);
assertEquals("Book of the week", bookOfTheWeek.getName());
@@ -138,10 +134,10 @@ void bookOfTheWeek_asDto_viaRestEndpoint() {
@Test @Order(6)
void multipleBooks_asDto_viaRestEndpoint() throws JAXBException {
- var digest = restService.getMultipleBooksAsDto(restfulClient)
+ var entity = restService.getMultipleBooksAsDto(restClient)
.ifFailureFail();
- var multipleBooks = digest.getValue().orElseThrow();
+ var multipleBooks = entity.valueAsNonNullElseFail();
assertEquals(2, multipleBooks.size());
@@ -152,10 +148,8 @@ void multipleBooks_asDto_viaRestEndpoint() throws
JAXBException {
@Test @Order(7)
void inventoryAsJaxbVm_viaRestEndpoint() {
- var digest = restService.getInventoryAsJaxbVm(restfulClient)
- .ifFailureFail();
-
- final JpaInventoryJaxbVm inventoryAsJaxbVm =
digest.getValue().orElseThrow();
+ final JpaInventoryJaxbVm inventoryAsJaxbVm =
restService.getInventoryAsJaxbVm(restClient)
+ .valueAsNonNullElseFail();
assertNotNull(inventoryAsJaxbVm);
assertEquals("Bookstore", inventoryAsJaxbVm.getName());
@@ -163,10 +157,10 @@ void inventoryAsJaxbVm_viaRestEndpoint() {
@Test @Order(8)
void listBooks_fromInventoryAsJaxbVm_viaRestEndpoint() {
- var digest = restService.getBooksFromInventoryAsJaxbVm(restfulClient)
+ var entity = restService.getBooksFromInventoryAsJaxbVm(restClient)
.ifFailure(Assertions::fail);
- var books = digest.getValue().orElseThrow();
+ var books = entity.valueAsNonNullElseFail();
var expectedBookTitles = JpaTestFixtures.expectedBookTitles();
@@ -192,10 +186,10 @@ void calendarEvent_echo_viaRestEndpoint() {
* "cardinality":4
* }
*/
- var digest = restService.echoCalendarEvent(restfulClient, calSample)
+ var entity = restService.echoCalendarEvent(restClient, calSample)
.ifFailure(Assertions::fail);
- var calSampleEchoed = digest.getValue().orElseThrow();
+ var calSampleEchoed = entity.valueAsNonNullElseFail();
assertEquals(calSample, calSampleEchoed);
}
diff --git a/viewers/restfulobjects/applib/src/main/java/module-info.java
b/viewers/restfulobjects/applib/src/main/java/module-info.java
index ccc5b76f788..a4d25379a87 100644
--- a/viewers/restfulobjects/applib/src/main/java/module-info.java
+++ b/viewers/restfulobjects/applib/src/main/java/module-info.java
@@ -36,7 +36,7 @@
requires com.fasterxml.jackson.annotation;
requires com.fasterxml.jackson.core;
requires com.fasterxml.jackson.databind;
- requires org.apache.causeway.applib;
+ requires transitive org.apache.causeway.applib;
requires org.apache.causeway.commons;
requires spring.context;
requires spring.core;
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/ActionParameterModel.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/ActionParameterModel.java
index d55adafe628..bb4c68103c5 100644
---
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/ActionParameterModel.java
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/ActionParameterModel.java
@@ -65,4 +65,5 @@ static ActionParameterModel create(String baseUrl) {
}
String toJson();
+
}
\ No newline at end of file
diff --git
a/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/CausewayMediaTypes.java
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/CausewayMediaTypes.java
new file mode 100644
index 00000000000..50afbe40e1c
--- /dev/null
+++
b/viewers/restfulobjects/applib/src/main/java/org/apache/causeway/viewer/restfulobjects/applib/client/CausewayMediaTypes.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.causeway.viewer.restfulobjects.applib.client;
+
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+
+import org.springframework.http.MediaType;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.LinkedCaseInsensitiveMap;
+import org.springframework.util.StringUtils;
+
+import org.apache.causeway.applib.client.SuppressionType;
+import org.apache.causeway.commons.internal.base._Strings;
+
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class CausewayMediaTypes {
+
+ public final MediaType CAUSEWAY_XML = profile(MediaType.APPLICATION_XML,
"urn:org.restfulobjects:repr-types/action-result");
+ public final MediaType CAUSEWAY_JSON_V2 =
profile(MediaType.APPLICATION_JSON, "urn:org.apache.causeway/v2");
+ public final MediaType CAUSEWAY_JSON_V2_LIGHT = suppress(CAUSEWAY_JSON_V2,
SuppressionType.all());
+
+ public MediaType appendParameter(MediaType input, String name, String
value) {
+ if(!StringUtils.hasLength(name)) return input;
+ value = _Strings.nullToEmpty(value);
+
+ var parameters = input.getParameters();
+ if (!CollectionUtils.isEmpty(parameters)) {
+ var map = new LinkedCaseInsensitiveMap<String>(parameters.size(),
Locale.ROOT);
+ map.put(name, value);
+ parameters.forEach(map::put);
+ return new MediaType(input, map);
+ }
+ return new MediaType(input, Map.of(name, value));
+ }
+
+ public MediaType profile(MediaType input, String urn) {
+ if(!StringUtils.hasLength(urn)) return input;
+
+ urn = _Strings.prefix(urn, "\"");
+ urn = _Strings.suffix(urn, "\"");
+
+ return appendParameter(input, "profile", urn);
+ }
+
+ public MediaType suppress(MediaType input, EnumSet<SuppressionType>
suppressionTypes) {
+ return SuppressionType.toLiteral(suppressionTypes)
+ .map(value->appendParameter(input, "suppress", value))
+ .orElse(input);
+ }
+
+ public MediaType domainType(MediaType input, Class<?> domainType) {
+ return Optional.ofNullable(domainType)
+ .map(Class::getName)
+ .map(name->appendParameter(input, "x-ro-domain-type", name))
+ .orElse(input);
+ }
+
+}
diff --git
a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ActionParameterModelRecord.java
b/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ActionParameterModelRecord.java
deleted file mode 100644
index 10ceb669f72..00000000000
---
a/viewers/restfulobjects/client/src/main/java/org/apache/causeway/viewer/restfulobjects/client/ActionParameterModelRecord.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.causeway.viewer.restfulobjects.client;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import jakarta.ws.rs.client.Entity;
-
-import org.apache.causeway.applib.services.bookmark.Bookmark;
-
-import org.jspecify.annotations.Nullable;
-
-import org.apache.causeway.applib.util.schema.CommonDtoUtils;
-import org.apache.causeway.applib.value.Blob;
-import org.apache.causeway.applib.value.Clob;
-import org.apache.causeway.applib.value.semantics.ValueDecomposition;
-import org.apache.causeway.commons.io.JsonUtils;
-import org.apache.causeway.schema.common.v2.BlobDto;
-import org.apache.causeway.schema.common.v2.ClobDto;
-import org.apache.causeway.schema.common.v2.ValueType;
-import org.apache.causeway.schema.common.v2.ValueWithTypeDto;
-
-import lombok.Getter;
-import org.jspecify.annotations.NonNull;
-
-/**
- * Use {@link RestfulClient#arguments()} to get an instance.
- * @since 2.0 {@index}
- */
-public class ActionParameterModelRecord {
-
- private final Map<String, String> actionParameters = new LinkedHashMap<>();
-
- @Getter
- private final Map<String, Class<?>> actionParameterTypes = new
LinkedHashMap<>();
-
- private final RestfulClient restfulClient;
-
- public ActionParameterModelRecord(RestfulClient restfulClient) {
- this.restfulClient = restfulClient;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final String parameterValue) {
- actionParameters.put(parameterName, parameterValue != null
- ? value("\"" + parameterValue + "\"")
- : value(JSON_NULL_LITERAL));
- actionParameterTypes.put(parameterName, String.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final int parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, int.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final long parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, long.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final byte parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, byte.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final short parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, short.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final double parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, double.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final float parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, float.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final boolean parameterValue) {
- actionParameters.put(parameterName, value(""+parameterValue));
- actionParameterTypes.put(parameterName, boolean.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final Blob blob) {
- var blobDto = new BlobDto();
- blobDto.setName(blob.name());
- blobDto.setMimeType(blob.mimeType().getBaseType());
- blobDto.setBytes(blob.bytes());
- var fundamentalTypeDto = new ValueWithTypeDto();
- fundamentalTypeDto.setType(ValueType.BLOB);
- fundamentalTypeDto.setBlob(blobDto);
- actionParameters.put(parameterName,
value(CommonDtoUtils.getFundamentalValueAsJson(fundamentalTypeDto)));
- actionParameterTypes.put(parameterName, Blob.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final Clob clob) {
- var clobDto = new ClobDto();
- clobDto.setName(clob.name());
- clobDto.setMimeType(clob.mimeType().getBaseType());
- clobDto.setChars(clob.asString());
- var fundamentalTypeDto = new ValueWithTypeDto();
- fundamentalTypeDto.setType(ValueType.CLOB);
- fundamentalTypeDto.setClob(clobDto);
- actionParameters.put(parameterName,
value(CommonDtoUtils.getFundamentalValueAsJson(fundamentalTypeDto)));
- actionParameterTypes.put(parameterName, Blob.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(final String
parameterName,
- final @NonNull Map<String, Object> map) {
- var nestedJson = JsonUtils.toStringUtf8(map);
- actionParameters.put(parameterName, value(nestedJson));
- actionParameterTypes.put(parameterName, Map.class);
- return this;
- }
-
- public ActionParameterModelRecord addActionParameter(
- final @NonNull String parameterName,
- final @NonNull Bookmark bookmark) {
- if (this.restfulClient == null) {
- throw new IllegalStateException("Use RestfulClient#arguments() to
create this builder");
- }
- actionParameters.put(parameterName, valueHref( bookmark) );
- actionParameterTypes.put(parameterName, Map.class);
- return this;
- }
-
- private String valueHref(Bookmark bookmark) {
- String hrefValue = asAbsoluteHref(bookmark);
-// String hrefValue = "\"" + asAbsoluteHref(bookmark) + "\"";
- Map<String, String> map = Map.of("href", hrefValue);
- return value(JsonUtils.toStringUtf8(map));
- }
-
- private String asAbsoluteHref(Bookmark bookmark) {
- return String.format("%s%s",
restfulClient.getConfig().getRestfulBaseUrl(), asRelativeHref(bookmark));
- }
-
- private String asRelativeHref(Bookmark bookmark) {
- return String.format("objects/%s/%s", bookmark.logicalTypeName(),
bookmark.identifier());
- }
-
- public <T> ActionParameterModelRecord addActionParameter(
- final String parameterName,
- final @NonNull Class<T> type,
- final @Nullable T object) {
- var nestedJson = object!=null
- ? JsonUtils.toStringUtf8(object)
- : "NULL"; // see ValueSerializerDefault.ENCODED_NULL
- actionParameters.put(parameterName, value(nestedJson));
- actionParameterTypes.put(parameterName, type);
- return this;
- }
-
- /**
- * For transport of {@link ValueDecomposition} over REST.
- * @see RestfulClient#digestValue(jakarta.ws.rs.core.Response,
org.apache.causeway.applib.value.semantics.ValueSemanticsProvider)
- */
- public ActionParameterModelRecord addActionParameter(final String
parameterName, final ValueDecomposition decomposition) {
- return addActionParameter(parameterName, decomposition.stringify());
- }
-
- public Entity<String> build() {
- final StringBuilder sb = new StringBuilder();
- sb.append("{\n")
- .append(actionParameters.entrySet().stream()
- .map(this::toJson)
- .collect(Collectors.joining(",\n")))
- .append("\n}");
-
- return Entity.json(sb.toString());
- }
-
- // -- HELPER
-
- private static final String JSON_NULL_LITERAL = "null";
-
- private String value(final String valueLiteral) {
- return "{\"value\" : " + valueLiteral + "}";
- }
-
- private String toJson(final Map.Entry<String, String> entry) {
- return " \""+entry.getKey()+"\": "+entry.getValue();
- }
-
-}
diff --git a/viewers/restfulobjects/test/pom.xml
b/viewers/restfulobjects/test/pom.xml
index cb2bfdff45d..a2ffa1f159f 100644
--- a/viewers/restfulobjects/test/pom.xml
+++ b/viewers/restfulobjects/test/pom.xml
@@ -41,19 +41,6 @@
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
- <build>
- <testResources>
- <testResource>
- <directory>src/test/resources</directory>
- <filtering>true</filtering>
- </testResource>
- <testResource>
- <directory>src/test/java</directory>
- <filtering>false</filtering>
- </testResource>
- </testResources>
- </build>
-
<dependencies>
<!-- TESTING -->
@@ -107,11 +94,6 @@
<artifactId>causeway-testing-fixtures-applib</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.apache.causeway.viewer</groupId>
-
<artifactId>causeway-viewer-restfulobjects-client</artifactId>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.apache.causeway.viewer</groupId>
<artifactId>causeway-viewer-restfulobjects-viewer</artifactId>
@@ -162,11 +144,5 @@
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <scope>test</scope>
- </dependency>
-
</dependencies>
</project>
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/CausewayViewerRestfulObjectsIntegTestAbstract.java
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/CausewayViewerRestfulObjectsIntegTestAbstract.java
index b9bc60f26b5..94c02e1dd2a 100644
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/CausewayViewerRestfulObjectsIntegTestAbstract.java
+++
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/CausewayViewerRestfulObjectsIntegTestAbstract.java
@@ -58,10 +58,6 @@
import org.apache.causeway.core.config.environment.CausewaySystemEnvironment;
import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
import
org.apache.causeway.viewer.restfulobjects.applib.client.ConversationLogger;
-import org.apache.causeway.viewer.restfulobjects.client.AuthenticationMode;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClient;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClientConfig;
-
import static
org.apache.causeway.commons.internal.assertions._Assert.assertNotNull;
import lombok.SneakyThrows;
@@ -173,19 +169,6 @@ public void handleError(final URI url, final HttpMethod
method, final ClientHttp
};
}
- @Deprecated
- protected RestfulClient restfulClient() {
- var clientConfig = RestfulClientConfig.builder()
- .restfulBaseUrl(String.format("http://0.0.0.0:%d/restful/",
port))
- .authenticationMode(AuthenticationMode.BASIC)
- .basicAuthUser("any") // using bypass auth.
- .basicAuthPassword("any")
- .useRequestDebugLogging(true) // default = false
- .build();
-
- return RestfulClient.ofConfig(clientConfig);
- }
-
public enum BookmarkOptions {
SCRUB,
PRESERVE
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/Abstract_IntegTest.java
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/Abstract_IntegTest.java
index 1cb87a5ad41..90827c8c3df 100644
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/Abstract_IntegTest.java
+++
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/Abstract_IntegTest.java
@@ -34,7 +34,6 @@
import org.springframework.transaction.annotation.Propagation;
import org.apache.causeway.applib.services.bookmark.BookmarkService;
import
org.apache.causeway.persistence.jpa.eclipselink.CausewayModulePersistenceJpaEclipselink;
-import org.apache.causeway.viewer.restfulobjects.client.RestfulClient;
import
org.apache.causeway.viewer.restfulobjects.test.CausewayViewerRestfulObjectsIntegTestAbstract;
import org.apache.causeway.viewer.restfulobjects.test.domain.UniversityModule;
import org.apache.causeway.viewer.restfulobjects.test.domain.dom.Department;
@@ -57,8 +56,6 @@ public abstract class Abstract_IntegTest extends
CausewayViewerRestfulObjectsInt
@Inject protected StaffMemberRepository staffMemberRepository;
@Inject protected BookmarkService bookmarkService;
- @Deprecated protected RestfulClient restfulClient;
-
protected Abstract_IntegTest(final Class<?> resourceBaseClazz) {
super(resourceBaseClazz);
}
@@ -96,14 +93,11 @@ protected void beforeEach(){
});
- restfulClient = restfulClient();
}
@Override
@AfterEach
protected void afterEach(){
- restfulClient.close();
-
transactionService.runTransactional(Propagation.REQUIRED, () -> {
staffMemberRepository.removeAll();
deptHeadRepository.findAll().forEach(x -> x.setDepartment(null));
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_MAP.approved.json
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_MAP.approved.json
similarity index 100%
rename from
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_MAP.approved.json
rename to
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_MAP.approved.json
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_VALUE.approved.json
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_VALUE.approved.json
similarity index 100%
rename from
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_VALUE.approved.json
rename to
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_BOOKMARK_AS_VALUE.approved.json
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_MAP.approved.json
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_MAP.approved.json
similarity index 100%
rename from
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_MAP.approved.json
rename to
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_MAP.approved.json
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_VALUE.approved.json
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_VALUE.approved.json
similarity index 100%
rename from
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_VALUE.approved.json
rename to
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.createStaffMemberWithPhoto.DEPARTMENT_KEY_AS_VALUE.approved.json
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.java
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.java
similarity index 97%
rename from
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.java
rename to
viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.java
index 94f01274006..f65e86f5a2a 100644
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_hilevel_IntegTest.java
+++
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_IntegTest.java
@@ -45,7 +45,7 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
-class Staff_hilevel_IntegTest extends Abstract_IntegTest {
+class Staff_IntegTest extends Abstract_IntegTest {
final String staffName = "Fred Smith";
@@ -153,7 +153,7 @@ private Blob readFileAsBlob(final String fileName) {
}
private String asAbsoluteHref(final Bookmark bookmark) {
- return String.format("%s%s",
restfulClient.getConfig().getRestfulBaseUrl(), asRelativeHref(bookmark));
+ return String.format("%s%s", baseUrl(), asRelativeHref(bookmark));
}
private String asRelativeHref(final Bookmark bookmark) {
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v1_IntegTest.createStaffMemberWithPhoto2.approved.json
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v1_IntegTest.createStaffMemberWithPhoto2.approved.json
deleted file mode 100644
index 5c1d9667211..00000000000
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v1_IntegTest.createStaffMemberWithPhoto2.approved.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name" : {
- "value" : "Fred Smith"
- },
- "department" : {
- "value" : {
- "href" :
"http://0.0.0.0:NNN/restful/objects/university.dept.Department/NNN"
- }
- },
- "photo" : {
- "value" :
"StaffMember-photo-Bar.pdf:application/pdf:JVBERi0xLjcNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhlbi1HQikgL1N0cnVjdFRyZWVSb290IDEyIDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4vTWV0YWRhdGEgMzIgMCBSL1ZpZXdlclByZWZlcmVuY2VzIDMzIDAgUj4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWyAzIDAgUl0gPj4NCmVuZG9iag0KMyAwIG9iag0KPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjEgNSAwIFIvRjIgOSAwIFI+Pi9FeHRHU3RhdGU8PC9HUzcgNyAwIFIvR1M4IDggMCB
[...]
- }
-}
\ No newline at end of file
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v1_IntegTest.java
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v1_IntegTest.java
deleted file mode 100644
index d634d95e942..00000000000
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v1_IntegTest.java
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.causeway.viewer.restfulobjects.test.scenarios.staff;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-
-import jakarta.activation.MimeType;
-import jakarta.activation.MimeTypeParseException;
-import jakarta.inject.Named;
-import jakarta.ws.rs.client.Entity;
-import jakarta.ws.rs.client.Invocation;
-import jakarta.ws.rs.core.Response;
-
-import com.google.gson.GsonBuilder;
-
-import org.approvaltests.Approvals;
-import org.approvaltests.reporters.DiffReporter;
-import org.approvaltests.reporters.UseReporter;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.springframework.context.annotation.Import;
-import org.springframework.stereotype.Component;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.annotation.DirtiesContext.MethodMode;
-import org.springframework.transaction.annotation.Propagation;
-
-import org.apache.causeway.applib.services.bookmark.Bookmark;
-import org.apache.causeway.applib.value.Blob;
-import org.apache.causeway.applib.value.NamedWithMimeType;
-import org.apache.causeway.applib.value.semantics.Renderer;
-import org.apache.causeway.applib.value.semantics.ValueDecomposition;
-import org.apache.causeway.applib.value.semantics.ValueSemanticsProvider;
-import org.apache.causeway.commons.collections.Can;
-import org.apache.causeway.commons.internal.base._Bytes;
-import org.apache.causeway.commons.internal.base._Strings;
-import org.apache.causeway.commons.io.DataSource;
-import org.apache.causeway.core.metamodel.valuesemantics.BlobValueSemantics;
-import org.apache.causeway.schema.common.v2.ValueType;
-import
org.apache.causeway.viewer.restfulobjects.test.scenarios.Abstract_IntegTest;
-
-import lombok.Getter;
-import lombok.SneakyThrows;
-
-@Import({
- Staff_lowlevel_v1_IntegTest.BlobValueSemanticsV1LegacyEncoding.class
-})
-class Staff_lowlevel_v1_IntegTest extends Abstract_IntegTest {
-
- @Test
- @UseReporter(DiffReporter.class)
- @DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
- @SneakyThrows
- void createStaffMemberWithPhoto2() {
-
- // given
- final var staffName = "Fred Smith";
-
- final var bookmarkBeforeIfAny =
transactionService.callTransactional(Propagation.REQUIRED, () -> {
- final var staffMember =
staffMemberRepository.findByName(staffName);
- return bookmarkService.bookmarkFor(staffMember);
- }).valueAsNonNullElseFail();
-
- assertThat(bookmarkBeforeIfAny).isEmpty();
-
- // and given
- final var departmentName = "Classics";
- final var departmentBookmark =
transactionService.callTransactional(Propagation.REQUIRED, () -> {
- final var staffMember =
departmentRepository.findByName(departmentName);
- return bookmarkService.bookmarkFor(staffMember).orElseThrow();
- }).valueAsNonNullElseFail();
-
- String departmentHref = asRelativeHref(departmentBookmark);
- Invocation.Builder departmentRequest =
restfulClient.request(departmentHref);
- Response departmentResponse = departmentRequest.get();
-
assertThat(departmentResponse.getStatusInfo().getFamily()).isEqualTo(Response.Status.Family.SUCCESSFUL);
-
- // and given
- final var photoEncoded =
readFileAndEncodeAsBlob("StaffMember-photo-Bar.pdf");
-
- // when create request
- final var requestBuilder =
restfulClient.request("services/university.dept.Staff/actions/createStaffMemberWithPhoto2/invoke");
-
- final var body = new Body(staffName,
asAbsoluteHref(departmentBookmark), photoEncoded);
- final var bodyJson = new GsonBuilder().create().toJson(body);
-
- // then
- Approvals.verify(bodyJson, jsonOptions());
-
- // and when send request
- var response = requestBuilder.post(Entity.entity(bodyJson,
"application/json"));
-
- // then
- assertResponseOK(response);
- var entity = response.readEntity(String.class);
- assertNotNull(entity);
-
- // and also object is created in database
- final var bookmarkAfterIfAny =
transactionService.callTransactional(Propagation.REQUIRED, () -> {
- final var staffMember =
staffMemberRepository.findByName(staffName);
- return bookmarkService.bookmarkFor(staffMember);
- }).valueAsNonNullElseFail();
- assertThat(bookmarkAfterIfAny).isNotEmpty();
- }
-
- private String asAbsoluteHref(final Bookmark bookmark) {
- return String.format("%s%s",
restfulClient.getConfig().getRestfulBaseUrl(), asRelativeHref(bookmark));
- }
-
- private String asRelativeHref(final Bookmark bookmark) {
- return String.format("objects/%s/%s", bookmark.logicalTypeName(),
bookmark.identifier());
- }
-
- private String readFileAndEncodeAsBlob(final String fileName) throws
IOException, URISyntaxException {
- var bytes = DataSource.ofResource(Abstract_IntegTest.class, fileName)
- .bytes();
- String photoEncoded = encodePdf(fileName, bytes);
- return photoEncoded;
- }
-
- private String encodePdf(final String fileName, final byte[] pdfBytes)
throws URISyntaxException {
- final String pdfBytesEncoded =
Base64.getEncoder().encodeToString(pdfBytes);
- final String encodedBlob = String.format("%s:%s:%s", fileName,
"application/pdf", pdfBytesEncoded);
- return encodedBlob;
- }
-
- @Getter
- static class Body {
-
- private Name name;
- private Department department;
- private Blob photo;
-
- /**
- * @param nameValue
- * @param departmentHrefValue
- * @param blobValue - is the Blob encoded format:
"filename.pdf:application/pdf:pdfBytesBase64Encoded"
- */
- Body(final String nameValue, final String departmentHrefValue, final
String blobValue) {
- photo = new Blob(blobValue);
- name = new Name(nameValue);
- department = new Department(new
Department.Value(departmentHrefValue));
- }
-
- record Name(String value) {
- }
-
- record Department(Value value) {
- record Value(String href) {
- }
- }
-
- record Blob(String value) {
- }
- }
-
- @Component
- @Named("causeway.metamodel.value.BlobValueSemanticsV1LegacyEncoding") //
must have different name to original
- static class BlobValueSemanticsV1LegacyEncoding
- extends BlobValueSemantics
- implements Renderer<Blob> {
-
- public BlobValueSemanticsV1LegacyEncoding() {
- }
-
- @Override
- public Class<Blob> getCorrespondingClass() {
- return Blob.class;
- }
-
- @Override
- public ValueType getSchemaValueType() {
- return ValueType.STRING;
- }
-
- // -- COMPOSER
-
- @Override
- public ValueDecomposition decompose(final Blob value) {
- return decomposeAsString(value, this::toEncodedString, () -> null);
- }
-
- @Override
- public Blob compose(final ValueDecomposition decomposition) {
- return composeFromString(decomposition, this::fromEncodedString,
()->null);
- }
-
- // RENDERER
-
- @Override
- public String titlePresentation(final ValueSemanticsProvider.Context
context, final Blob value) {
- return renderTitle(value, Blob::name);
- }
-
- @Override
- public String htmlPresentation(final ValueSemanticsProvider.Context
context, final Blob value) {
- return renderHtml(value, Blob::name);
- }
-
- private String toEncodedString(final Blob blob) {
- return blob.name() + ":" + blob.mimeType().getBaseType() + ":" +
- _Strings.ofBytes(_Bytes.encodeToBase64(Base64.getEncoder(),
blob.bytes()), StandardCharsets.UTF_8);
- }
-
- private Blob fromEncodedString(final String data) {
- final int colonIdx = data.indexOf(':');
- final String name = data.substring(0, colonIdx);
- final int colon2Idx = data.indexOf(":", colonIdx+1);
- final String mimeTypeBase = data.substring(colonIdx+1, colon2Idx);
- final String payload = data.substring(colon2Idx+1);
- final byte[] bytes = _Bytes.decodeBase64(Base64.getDecoder(),
payload.getBytes(StandardCharsets.UTF_8));
- try {
- return new Blob(name, new MimeType(mimeTypeBase), bytes);
- } catch (MimeTypeParseException e) {
- throw new RuntimeException(e);
- }
- }
-
- // -- EXAMPLES
-
- @Override
- public Can<Blob> getExamples() {
- return Can.of(
- Blob.of("a Blob", NamedWithMimeType.CommonMimeType.BIN,
new byte[] {1, 2, 3}),
- Blob.of("another Blob",
NamedWithMimeType.CommonMimeType.BIN, new byte[] {3, 4}));
- }
-
- }
-
-}
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v2_IntegTest.createStaffMemberWithPhoto2.approved.json
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v2_IntegTest.createStaffMemberWithPhoto2.approved.json
deleted file mode 100644
index a6123f9fb94..00000000000
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v2_IntegTest.createStaffMemberWithPhoto2.approved.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "name" : {
- "value" : "Fred Smith"
- },
- "department" : {
- "value" : {
- "href" :
"http://0.0.0.0:NNN/restful/objects/university.dept.Department/NNN"
- }
- },
- "photo" : {
- "value" : {
- "name" : "StaffMember-photo-Bar.pdf",
- "mimeType" : "application/pdf",
- "bytes" :
"JVBERi0xLjcNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhlbi1HQikgL1N0cnVjdFRyZWVSb290IDEyIDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4vTWV0YWRhdGEgMzIgMCBSL1ZpZXdlclByZWZlcmVuY2VzIDMzIDAgUj4+DQplbmRvYmoNCjIgMCBvYmoNCjw8L1R5cGUvUGFnZXMvQ291bnQgMS9LaWRzWyAzIDAgUl0gPj4NCmVuZG9iag0KMyAwIG9iag0KPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9Gb250PDwvRjEgNSAwIFIvRjIgOSAwIFI+Pi9FeHRHU3RhdGU8PC9HUzcgNyAwIFIvR1M4IDggMCBSPj4vUHJvY1NldFsvUERGL1RleHQvSW1hZ2VCL0l
[...]
- }
- }
-}
\ No newline at end of file
diff --git
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v2_IntegTest.java
b/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v2_IntegTest.java
deleted file mode 100644
index e5ee41e8fe6..00000000000
---
a/viewers/restfulobjects/test/src/test/java/org/apache/causeway/viewer/restfulobjects/test/scenarios/staff/Staff_lowlevel_v2_IntegTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.causeway.viewer.restfulobjects.test.scenarios.staff;
-
-import java.io.IOException;
-import java.util.Base64;
-
-import jakarta.ws.rs.client.Entity;
-import jakarta.ws.rs.client.Invocation;
-import jakarta.ws.rs.core.Response;
-
-import com.google.gson.GsonBuilder;
-
-import org.approvaltests.Approvals;
-import org.approvaltests.reporters.DiffReporter;
-import org.approvaltests.reporters.UseReporter;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.springframework.transaction.annotation.Propagation;
-
-import org.apache.causeway.applib.services.bookmark.Bookmark;
-import org.apache.causeway.applib.value.Blob;
-import org.apache.causeway.commons.io.DataSource;
-import
org.apache.causeway.viewer.restfulobjects.test.scenarios.Abstract_IntegTest;
-
-import lombok.Getter;
-import lombok.SneakyThrows;
-
-class Staff_lowlevel_v2_IntegTest extends Abstract_IntegTest {
-
- @Test
- @UseReporter(DiffReporter.class)
- @SneakyThrows
- public void createStaffMemberWithPhoto2() {
-
- // given
- final var staffName = "Fred Smith";
-
- final var bookmarkBeforeIfAny =
transactionService.callTransactional(Propagation.REQUIRED, () -> {
- final var staffMember =
staffMemberRepository.findByName(staffName);
- return bookmarkService.bookmarkFor(staffMember);
- }).valueAsNonNullElseFail();
-
- assertThat(bookmarkBeforeIfAny).isEmpty();
-
- // and given
- final var departmentName = "Classics";
- final var departmentBookmark =
transactionService.callTransactional(Propagation.REQUIRED, () -> {
- final var staffMember =
departmentRepository.findByName(departmentName);
- return bookmarkService.bookmarkFor(staffMember).orElseThrow();
- }).valueAsNonNullElseFail();
-
- String departmentHref = asRelativeHref(departmentBookmark);
- Invocation.Builder departmentRequest =
restfulClient.request(departmentHref);
- Response departmentResponse = departmentRequest.get();
-
assertThat(departmentResponse.getStatusInfo().getFamily()).isEqualTo(Response.Status.Family.SUCCESSFUL);
-
- // and given
- final var photoEncoded = readFileAsBlob("StaffMember-photo-Bar.pdf");
-
- // when create request
- final var requestBuilder =
restfulClient.request("services/university.dept.Staff/actions/createStaffMemberWithPhoto2/invoke");
-
- final var body = new Body(staffName,
asAbsoluteHref(departmentBookmark), photoEncoded);
- final var bodyJson = new GsonBuilder().create().toJson(body);
-
- // then
- Approvals.verify(bodyJson, jsonOptions());
-
- // and when send request
- var response = requestBuilder.post(Entity.entity(bodyJson,
"application/json"));
-
- // then
- assertResponseOK(response);
- var entity = response.readEntity(String.class);
- assertNotNull(entity);
-
- // and also object is created in database
- final var bookmarkAfterIfAny =
transactionService.callTransactional(Propagation.REQUIRED, () -> {
- final var staffMember =
staffMemberRepository.findByName(staffName);
- return bookmarkService.bookmarkFor(staffMember);
- }).valueAsNonNullElseFail();
- assertThat(bookmarkAfterIfAny).isNotEmpty();
- }
-
- private String asAbsoluteHref(final Bookmark bookmark) {
- return String.format("%s%s",
restfulClient.getConfig().getRestfulBaseUrl(), asRelativeHref(bookmark));
- }
-
- private String asRelativeHref(final Bookmark bookmark) {
- return String.format("objects/%s/%s", bookmark.logicalTypeName(),
bookmark.identifier());
- }
-
- private Blob readFileAsBlob(final String fileName) throws IOException {
- var bytes = DataSource.ofResource(Abstract_IntegTest.class, fileName)
- .bytes();
- return new Blob(fileName, "application/pdf", bytes);
- }
-
- @Getter
- static class Body {
-
- private Name name;
- private Department department;
- private Blob photo;
-
- /**
- * @param nameValue
- * @param departmentHrefValue
- * @param blob - is the Blob to be formatted
- */
- Body(final String nameValue, final String departmentHrefValue, final
org.apache.causeway.applib.value.Blob blob) {
- name = new Name(nameValue);
- department = new Department(new
Department.Value(departmentHrefValue));
- photo = new Blob(new Blob.Value(blob.name(),
blob.mimeType().toString(), Base64.getEncoder().encodeToString(blob.bytes())));
- }
-
- record Name(String value) {
- }
-
- record Department(Value value) {
- record Value(String href) {
- }
- }
-
- record Blob(Value value) {
- record Value(
- String name,
- String mimeType,
- String bytes) {
- }
- }
-
- }
-
-}