This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-3668
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit f8858b1575a1e60fb23a5b59fac82c7d4093a936
Author: danhaywood <[email protected]>
AuthorDate: Fri Jan 12 07:34:28 2024 +0000

    CAUSEWAY-3668: wip - the EmailServiceDefault_IntegTest throws a 
ClassNotFoundException
    
    ... can't work out why as of yet...
---
 api/applib/src/main/java/module-info.java          |  10 +-
 api/schema/src/main/java/module-info.java          |   3 +
 bom/pom.xml                                        |  19 ----
 .../src/main/java/module-info.java                 |   2 +
 .../core/config/CausewayConfiguration.java         |  82 +++++++++++++--
 core/interaction/src/main/java/module-info.java    |   2 +
 .../metamodel/facets/object/icon/ObjectIcon.java   |   3 +
 core/runtime/src/main/java/module-info.java        |   3 +
 core/runtimeservices/pom.xml                       |  81 +++++---------
 .../runtimeservices/src/main/java/module-info.java |  23 +++-
 .../runtimeservices/email/EmailServiceDefault.java |  76 +++++---------
 .../email/EmailServiceDefault_IntegTest.java       | 116 +++++++++++++++++++++
 .../src/test/resources/application.yml             |  16 +++
 core/security/src/main/java/module-info.java       |   2 +
 core/transaction/src/main/java/module-info.java    |   4 +
 incubator/viewers/graphql/test/pom.xml             |   1 -
 .../integration/src/main/java/module-info.java     |   3 +-
 17 files changed, 304 insertions(+), 142 deletions(-)

diff --git a/api/applib/src/main/java/module-info.java 
b/api/applib/src/main/java/module-info.java
index ba3c1d6f38..044fc9e415 100644
--- a/api/applib/src/main/java/module-info.java
+++ b/api/applib/src/main/java/module-info.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-module org.apache.causeway.applib {
+open module org.apache.causeway.applib {
     exports org.apache.causeway.applib;
     exports org.apache.causeway.applib.annotation;
     exports org.apache.causeway.applib.client;
@@ -146,13 +146,5 @@ module org.apache.causeway.applib {
     requires transitive spring.core;
     requires spring.tx;
 
-    // JAXB viewmodels
-    opens org.apache.causeway.applib.annotation;
-    opens org.apache.causeway.applib.layout.component;
-    opens org.apache.causeway.applib.layout.grid.bootstrap;
-    opens org.apache.causeway.applib.layout.grid;
-    opens org.apache.causeway.applib.layout.links;
-    opens org.apache.causeway.applib.layout.menubars.bootstrap;
-    opens org.apache.causeway.applib.layout.menubars;
 
 }
diff --git a/api/schema/src/main/java/module-info.java 
b/api/schema/src/main/java/module-info.java
index 13e529690f..834dbaa4e9 100644
--- a/api/schema/src/main/java/module-info.java
+++ b/api/schema/src/main/java/module-info.java
@@ -27,10 +27,13 @@ module org.apache.causeway.schema {
     requires java.xml.bind;
     requires spring.context;
     requires java.inject;
+    requires spring.core;
 
     opens org.apache.causeway.schema.metamodel.v2;
     opens org.apache.causeway.schema.common.v2;
     opens org.apache.causeway.schema.cmd.v2;
     opens org.apache.causeway.schema.ixn.v2;
     opens org.apache.causeway.schema.chg.v2;
+
+    opens org.apache.causeway.schema to spring.core;
 }
\ No newline at end of file
diff --git a/bom/pom.xml b/bom/pom.xml
index 926a20bbd8..bc9f2791c4 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -95,7 +95,6 @@ It is therefore a copy of org.apache:apache, with 
customisations clearly identif
 
         <camel.version>3.14.9</camel.version>
 
-        <commons-email.version>1.6.0</commons-email.version>
         <commons-httpclient.version>4.5.12</commons-httpclient.version>
         <commons-io.version>2.15.1</commons-io.version>
 
@@ -1692,24 +1691,6 @@ It is therefore a copy of org.apache:apache, with 
customisations clearly identif
                                </exclusions>
                        </dependency>
 
-                       <!-- TODO: when used, move exclusions down -->
-                       <dependency>
-                               <groupId>org.apache.commons</groupId>
-                               <artifactId>commons-email</artifactId>
-                               <version>${commons-email.version}</version>
-                               <exclusions>
-                                       <!-- excluded because provided by 
javax:javaee-api -->
-                                       <exclusion>
-                                               <groupId>com.sun.mail</groupId>
-                                               
<artifactId>javax.mail</artifactId>
-                                       </exclusion>
-                                       <exclusion>
-                                               
<groupId>javax.activation</groupId>
-                                               
<artifactId>activation</artifactId>
-                                       </exclusion>
-                               </exclusions>
-                       </dependency>
-
                        <dependency>
                                <groupId>org.apache.cxf</groupId>
                                <artifactId>cxf-rt-rs-client</artifactId>
diff --git a/core/codegen-bytebuddy/src/main/java/module-info.java 
b/core/codegen-bytebuddy/src/main/java/module-info.java
index 8cb44477ee..a99ae74069 100644
--- a/core/codegen-bytebuddy/src/main/java/module-info.java
+++ b/core/codegen-bytebuddy/src/main/java/module-info.java
@@ -24,4 +24,6 @@ module org.apache.causeway.core.codegen.bytebuddy {
     requires org.apache.causeway.commons;
     requires spring.context;
     requires spring.core;
+
+    opens org.apache.causeway.core.codegen.bytebuddy to spring.core;
 }
\ No newline at end of file
diff --git 
a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
 
b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
index 2244a195e4..67e6ff93cb 100644
--- 
a/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
+++ 
b/core/config/src/main/java/org/apache/causeway/core/config/CausewayConfiguration.java
@@ -57,6 +57,7 @@ import javax.validation.constraints.NotNull;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.ConfigurationProperties;
+import 
org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
 import org.springframework.boot.info.BuildProperties;
 import org.springframework.core.env.ConfigurableEnvironment;
 import org.springframework.validation.annotation.Validated;
@@ -1775,18 +1776,46 @@ public class CausewayConfiguration {
             private final Email email = new Email();
             @Data
             public static class Email {
+
+                @Deprecated
+                private int port = 587;
+
                 /**
                  * The port to use for sending email.
+                 *
+                 * @deprecated  - ignored, instead use 
<code>spring.mail.port</code>
                  */
-                private int port = 587;
+                @DeprecatedConfigurationProperty(replacement = 
"spring.mail.port")
+                public int getPort() {
+                    return port;
+                }
+
+                @Deprecated
+                private int socketConnectionTimeout = 2000;
+
                 /**
                  * The maximum number of millseconds to wait to obtain a 
socket connection before timing out.
+                 *
+                 * @deprecated  - ignored, instead use 
<code>spring.mail.properties.mail.smtp.connectiontimeout</code>
                  */
-                private int socketConnectionTimeout = 2000;
+                @DeprecatedConfigurationProperty(replacement = 
"spring.mail.properties.mail.smtp.connectiontimeout")
+                public int getSocketConnectionTimeout() {
+                    return socketConnectionTimeout;
+                }
+
+                @Deprecated
+                private int socketTimeout = 2000;
+
                 /**
                  * The maximum number of millseconds to wait to obtain a 
socket before timing out.
+                 *
+                 * @deprecated  - ignored, instead use 
<code>spring.mail.properties.mail.smtp.timeout</code>
                  */
-                private int socketTimeout = 2000;
+                @DeprecatedConfigurationProperty(replacement = 
"spring.mail.properties.mail.smtp.timeout")
+                public int getSocketTimeout() {
+                    return socketTimeout;
+                }
+
                 /**
                  * If an email fails to send, whether to propagate the 
exception (meaning that potentially the end-user
                  * might see the exception), or whether instead to just 
indicate failure through the return value of
@@ -1821,6 +1850,10 @@ public class CausewayConfiguration {
                 private final Sender sender = new Sender();
                 @Data
                 public static class Sender {
+
+                    @Deprecated
+                    private String hostname;
+
                     /**
                      * Specifies the host running the SMTP service.
                      *
@@ -1828,16 +1861,35 @@ public class CausewayConfiguration {
                      *     If not specified, then the value used depends upon 
the email implementation.  The default
                      *     implementation will use the 
<code>mail.smtp.host</code> system property.
                      * </p>
+                     *
+                     * @deprecated - now ignored, instead use 
<code>spring.mail.host</code>
                      */
-                    private String hostname;
+                    @DeprecatedConfigurationProperty(replacement = 
"spring.mail.host")
+                    public String getHostname() {
+                        return hostname;
+                    }
+
+                    @Deprecated
+                    private String username;
+
                     /**
                      * Specifies the username to use to connect to the SMTP 
service.
                      *
                      * <p>
                      *     If not specified, then the sender's {@link 
#getAddress() email address} will be used instead.
                      * </p>
+                     *
+                     * @deprecated - now ignored, instead use 
<code>spring.mail.username</code>
                      */
-                    private String username;
+                    @DeprecatedConfigurationProperty(replacement = 
"spring.mail.username")
+                    public String getUsername() {
+                        return username;
+                    }
+
+                    @Deprecated
+                    private String password;
+
+
                     /**
                      * Specifies the password (corresponding to the {@link 
#getUsername() username} to connect to the
                      * SMTP service.
@@ -1846,8 +1898,14 @@ public class CausewayConfiguration {
                      *     This configuration property is mandatory (for the 
default implementation of the
                      *     {@link 
org.apache.causeway.applib.services.email.EmailService}, at least).
                      * </p>
+                     *
+                     * @deprecated - now ignored, instead use 
<code>spring.mail.password</code>
                      */
-                    private String password;
+                    @DeprecatedConfigurationProperty(replacement = 
"spring.mail.password")
+                    public String getPassword() {
+                        return password;
+                    }
+
                     /**
                      * Specifies the email address of the user sending the 
email.
                      *
@@ -1865,13 +1923,23 @@ public class CausewayConfiguration {
                     private String address;
                 }
 
+                @Deprecated
                 private final Tls tls = new Tls();
+                @Deprecated
                 @Data
                 public static class Tls {
+                    @Deprecated
+                    private boolean enabled = true;
+
                     /**
                      * Whether TLS encryption should be started (that is, 
<code>STARTTLS</code>).
+                     *
+                     * @deprecated  - now ignored, instead use 
<code>spring.mail.javamail.properties.mail.smtp.starttls.enable</code>
                      */
-                    private boolean enabled = true;
+                    @DeprecatedConfigurationProperty(replacement = 
"spring.mail.javamail.properties.mail.smtp.starttls.enable")
+                    public boolean isEnabled() {
+                        return enabled;
+                    }
                 }
             }
 
diff --git a/core/interaction/src/main/java/module-info.java 
b/core/interaction/src/main/java/module-info.java
index c13a521cc3..7ef91b2946 100644
--- a/core/interaction/src/main/java/module-info.java
+++ b/core/interaction/src/main/java/module-info.java
@@ -35,4 +35,6 @@ module org.apache.causeway.core.interaction {
     requires spring.context;
     requires spring.core;
     requires spring.tx;
+
+    opens org.apache.causeway.core.interaction to spring.core;
 }
\ No newline at end of file
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
index 6336cb87e6..fe114176df 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/ObjectIcon.java
@@ -57,6 +57,9 @@ implements Serializable {
             final String shortName,
             final URL url,
             final CommonMimeType mimeType) {
+        if (url == null) {
+            return null;
+        }
         val id = _Strings.base64UrlEncode(url.getPath());
         val objectIcon = new ObjectIcon(shortName, url, mimeType, id);
         objectIcon.asBytes(); // memoize
diff --git a/core/runtime/src/main/java/module-info.java 
b/core/runtime/src/main/java/module-info.java
index 7ab79ba1ae..b527c4485a 100644
--- a/core/runtime/src/main/java/module-info.java
+++ b/core/runtime/src/main/java/module-info.java
@@ -36,4 +36,7 @@ module org.apache.causeway.core.runtime {
     requires spring.context;
     requires spring.core;
     requires spring.tx;
+
+    opens org.apache.causeway.core.runtime to spring.core;
+    opens org.apache.causeway.core.runtime.events to spring.core;
 }
\ No newline at end of file
diff --git a/core/runtimeservices/pom.xml b/core/runtimeservices/pom.xml
index f1b8a346b8..54aecd1d92 100644
--- a/core/runtimeservices/pom.xml
+++ b/core/runtimeservices/pom.xml
@@ -71,17 +71,12 @@
     </build>
 
     <dependencies>
-               
-               <dependency>
-                   <groupId>jakarta.mail</groupId>
-                   <artifactId>jakarta.mail-api</artifactId>
-               </dependency>
-       
+
         <dependency>
             <groupId>org.apache.causeway.core</groupId>
             <artifactId>causeway-core-runtime</artifactId>
         </dependency>
-      
+
         <dependency>
             <groupId>org.apache.causeway.core</groupId>
             <artifactId>causeway-core-codegen-bytebuddy</artifactId>
@@ -92,7 +87,23 @@
                 </exclusion>
             </exclusions>
         </dependency>
-        
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+
                <!-- TESTING -->
 
         <dependency>
@@ -109,53 +120,13 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>com.icegreen</groupId>
+            <artifactId>greenmail-junit5</artifactId>
+            <version>1.6.11</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
-    
-    <profiles>
-        <profile>
-            <id>email-notification-service</id>
-            <activation>
-                <property>
-                    <name>!skip.email-notification-service</name>
-                </property>
-            </activation>
-            <dependencies>
-                <dependency>
-                    <groupId>org.apache.commons</groupId>
-                    <artifactId>commons-email</artifactId>
-                    <exclusions>
-                        <!--
-                        excluded because provided by javax:javaee-api
-                        note: moved javax.mail from 1.5.2 to 1.5.0
-                        note: moved activation from 1.1.1 to 1.1    ... don't 
know if this is significant.
-                        -->
-                        <exclusion>
-                            <groupId>com.sun.mail</groupId>
-                            <artifactId>javax.mail</artifactId>
-                        </exclusion>
-                        <exclusion>
-                            <groupId>javax.activation</groupId>
-                            <artifactId>activation</artifactId>
-                        </exclusion>
-                    </exclusions>
-                </dependency>
-                <dependency>
-                                       <!-- required by EmailServiceDefault -->
-                               <groupId>com.sun.mail</groupId>
-                               <artifactId>jakarta.mail</artifactId>
-                               <exclusions>
-                                       <exclusion>
-                            <groupId>javax.activation</groupId>
-                            <artifactId>activation</artifactId>
-                           </exclusion>
-                           <exclusion>
-                               <groupId>com.sun.activation</groupId>
-                                               
<artifactId>jakarta.activation</artifactId>
-                                       </exclusion>
-                    </exclusions>
-                               </dependency>
-            </dependencies>
-        </profile>
-    </profiles>
 
 </project>
diff --git a/core/runtimeservices/src/main/java/module-info.java 
b/core/runtimeservices/src/main/java/module-info.java
index 8ed811dcf5..2127b7da3f 100644
--- a/core/runtimeservices/src/main/java/module-info.java
+++ b/core/runtimeservices/src/main/java/module-info.java
@@ -54,7 +54,6 @@ module org.apache.causeway.core.runtimeservices {
     exports org.apache.causeway.core.runtimeservices.xml;
     exports org.apache.causeway.core.runtimeservices.xmlsnapshot;
 
-    requires org.apache.commons.mail;
     requires jakarta.activation;
     requires jakarta.mail;
     requires java.annotation;
@@ -80,7 +79,29 @@ module org.apache.causeway.core.runtimeservices {
     requires spring.tx;
     requires org.apache.causeway.core.codegen.bytebuddy;
     requires spring.aop;
+    requires spring.context.support;
+
+    opens org.apache.causeway.core.runtimeservices to spring.core;
+    opens org.apache.causeway.core.runtimeservices.bookmarks to spring.core;
+    opens org.apache.causeway.core.runtimeservices.command to spring.core;
+    opens org.apache.causeway.core.runtimeservices.email to spring.core;
+    opens org.apache.causeway.core.runtimeservices.eventbus to spring.core;
+    opens org.apache.causeway.core.runtimeservices.factory to spring.core;
+    opens org.apache.causeway.core.runtimeservices.i18n.po to spring.core;
+    opens org.apache.causeway.core.runtimeservices.icons to spring.core;
+    opens org.apache.causeway.core.runtimeservices.scratchpad to spring.core;
+    opens org.apache.causeway.core.runtimeservices.message to spring.core;
+    opens org.apache.causeway.core.runtimeservices.menubars to spring.beans;
+    opens org.apache.causeway.core.runtimeservices.placeholder to spring.core;
+    opens org.apache.causeway.core.runtimeservices.interaction to spring.core;
+    opens org.apache.causeway.core.runtimeservices.publish to spring.core;
+    opens org.apache.causeway.core.runtimeservices.recognizer to spring.core;
+    opens org.apache.causeway.core.runtimeservices.serializing to spring.core;
+    opens org.apache.causeway.core.runtimeservices.user to spring.core;
+    opens org.apache.causeway.core.runtimeservices.userreg to spring.core;
 
     opens org.apache.causeway.core.runtimeservices.wrapper;
     opens org.apache.causeway.core.runtimeservices.wrapper.proxy; //to 
org.apache.causeway.core.codegen.bytebuddy
+
+
 }
diff --git 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault.java
index 15115cddeb..b491d06f94 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault.java
@@ -27,12 +27,13 @@ import javax.annotation.PostConstruct;
 import javax.annotation.Priority;
 import javax.inject.Inject;
 import javax.inject.Named;
+import javax.inject.Provider;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
 
-import org.apache.commons.mail.DefaultAuthenticator;
-import org.apache.commons.mail.EmailException;
-import org.apache.commons.mail.ImageHtmlEmail;
-import org.apache.commons.mail.resolver.DataSourceClassPathResolver;
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
 import org.springframework.stereotype.Service;
 
 import org.apache.causeway.applib.annotation.PriorityPrecedence;
@@ -42,6 +43,7 @@ import org.apache.causeway.core.config.CausewayConfiguration;
 import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
 
 import lombok.extern.log4j.Log4j2;
+import lombok.val;
 
 /**
  * A service that sends email notifications when specific events occur
@@ -56,13 +58,16 @@ public class EmailServiceDefault implements EmailService {
     private static final long serialVersionUID = 1L;
     public static class EmailServiceException extends RuntimeException {
         static final long serialVersionUID = 1L;
-        public EmailServiceException(final EmailException cause) {
+        public EmailServiceException(final Exception cause) {
             super(cause);
         }
     }
 
     @Inject private CausewayConfiguration configuration;
 
+    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
+    @Inject private Provider<JavaMailSender> emailSenderProvider;
+
     // -- INIT
 
     private boolean initialized;
@@ -142,6 +147,7 @@ public class EmailServiceDefault implements EmailService {
         return !_Strings.isNullOrEmpty(senderEmailAddress) && 
!_Strings.isNullOrEmpty(senderEmailPassword);
     }
 
+
     @Override
     public boolean send(
             final List<String> toList,
@@ -152,76 +158,48 @@ public class EmailServiceDefault implements EmailService {
             final DataSource... attachments) {
 
         try {
-            final ImageHtmlEmail email = new ImageHtmlEmail();
-
-            final String senderEmailUsername = getSenderEmailUsername();
-            final String senderEmailAddress = getSenderEmailAddress();
-            final String senderEmailPassword = getSenderEmailPassword();
-            final String senderEmailHostName = getSenderEmailHostName();
-            final Integer senderEmailPort = getSenderEmailPort();
-            final Boolean senderEmailTlsEnabled = getSenderEmailTlsEnabled();
-            final int socketTimeout = getSocketTimeout();
-            final int socketConnectionTimeout = getSocketConnectionTimeout();
-
-            if (senderEmailUsername != null) {
-                email.setAuthenticator(new 
DefaultAuthenticator(senderEmailUsername, senderEmailPassword));
-            } else {
-                email.setAuthenticator(new 
DefaultAuthenticator(senderEmailAddress, senderEmailPassword));
-            }
-            email.setHostName(senderEmailHostName);
-            email.setSmtpPort(senderEmailPort);
-            email.setStartTLSEnabled(senderEmailTlsEnabled);
-            email.setDataSourceResolver(new DataSourceClassPathResolver("/", 
true));
 
-            email.setSocketTimeout(socketTimeout);
-            email.setSocketConnectionTimeout(socketConnectionTimeout);
+            val javaMailSender = emailSenderProvider.get();
 
-            final Properties properties = 
email.getMailSession().getProperties();
+            val email = javaMailSender.createMimeMessage();
+            val emailHelper = new MimeMessageHelper(email, true);
 
-            properties.put("mail.smtps.auth", "true");
-            properties.put("mail.debug", "true");
-            properties.put("mail.smtps.port", "" + senderEmailPort);
-            properties.put("mail.smtps.socketFactory.port", "" + 
senderEmailPort);
-            properties.put("mail.smtps.socketFactory.class", 
"javax.net.ssl.SSLSocketFactory");
-            properties.put("mail.smtps.socketFactory.fallback", "false");
-            properties.put("mail.smtp.starttls.enable", "" + 
senderEmailTlsEnabled);
+            emailHelper.setFrom(getSenderEmailAddress());
 
-            email.setFrom(senderEmailAddress);
+            emailHelper.setSubject(subject);
+            boolean html = true;
+            emailHelper.setText(body, html);
 
-            email.setSubject(subject);
-            email.setHtmlMsg(body);
-
-            if (attachments != null && attachments.length > 0) {
+            if (attachments != null) {
                 for (DataSource attachment : attachments) {
-                    email.attach(attachment, attachment.getName(), "");
+                    emailHelper.addAttachment(attachment.getName(), 
attachment);
                 }
             }
 
-
             final String overrideToList = getEmailOverrideTo();
             final String overrideCc = getEmailOverrideCc();
             final String overrideBcc = getEmailOverrideBcc();
 
             final String[] toListElseOverride = 
originalUnlessOverridden(toList, overrideToList);
             if (notEmpty(toListElseOverride)) {
-                email.addTo(toListElseOverride);
+                emailHelper.setTo(toListElseOverride);
             }
             final String[] ccListElseOverride = 
originalUnlessOverridden(ccList, overrideCc);
             if (notEmpty(ccListElseOverride)) {
-                email.addCc(ccListElseOverride);
+                emailHelper.setCc(ccListElseOverride);
             }
             final String[] bccListElseOverride = 
originalUnlessOverridden(bccList, overrideBcc);
             if (notEmpty(bccListElseOverride)) {
-                email.addBcc(bccListElseOverride);
+                emailHelper.setBcc(bccListElseOverride);
             }
 
-            email.send();
+            javaMailSender.send(email);
 
-        } catch (EmailException ex) {
-            log.error("An error occurred while trying to send an email", ex);
+        } catch (MessagingException e) {
+            log.error("An error occurred while trying to send an email", e);
             final Boolean throwExceptionOnFail = isThrowExceptionOnFail();
             if (throwExceptionOnFail) {
-                throw new EmailServiceException(ex);
+                throw new EmailServiceException(e);
             }
             return false;
         }
diff --git 
a/core/runtimeservices/src/test/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault_IntegTest.java
 
b/core/runtimeservices/src/test/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault_IntegTest.java
new file mode 100644
index 0000000000..3f53dcd099
--- /dev/null
+++ 
b/core/runtimeservices/src/test/java/org/apache/causeway/core/runtimeservices/email/EmailServiceDefault_IntegTest.java
@@ -0,0 +1,116 @@
+package org.apache.causeway.core.runtimeservices.email;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.services.iactnlayer.InteractionContext;
+import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
+
+import org.apache.causeway.core.security.authentication.AuthenticationRequest;
+import 
org.apache.causeway.core.security.authentication.standard.AuthenticatorAbstract;
+
+import org.apache.causeway.core.security.authorization.Authorizor;
+
+import org.json.JSONException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayNameGeneration;
+import org.junit.jupiter.api.DisplayNameGenerator;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+
+import com.icegreen.greenmail.configuration.GreenMailConfiguration;
+import com.icegreen.greenmail.junit5.GreenMailExtension;
+import com.icegreen.greenmail.util.GreenMailUtil;
+import com.icegreen.greenmail.util.ServerSetupTest;
+
+@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
+@SpringBootTest(
+        classes = {EmailServiceDefault_IntegTest.TestApp.class},
+        webEnvironment = SpringBootTest.WebEnvironment.NONE
+)
+@Profile("test")
+class EmailServiceDefault_IntegTest {
+
+    @SpringBootConfiguration
+    @EnableAutoConfiguration
+    @Import({
+            CausewayModuleCoreRuntimeServices.class,
+
+            AuthenticatorDummy.class,
+            AuthorizorDummy.class,
+    })
+    public static class TestApp {
+    }
+
+    // a copy of AuthenticatorBypass from bypass module.
+    @Service
+    public static class AuthenticatorDummy extends AuthenticatorAbstract {
+
+        @Override
+        public boolean isValid(final AuthenticationRequest request) {
+            return true;
+        }
+
+        @Override
+        public boolean canAuthenticate(final Class<? extends 
AuthenticationRequest> authenticationRequestClass) {
+            return true;
+        }
+    }
+
+    // a copy of AuthorizorBypass from bypass module.
+    @Service
+    public static class AuthorizorDummy implements Authorizor {
+
+        @Override
+        public boolean isVisible(final InteractionContext authentication, 
final Identifier identifier) {
+            return true;
+        }
+
+        @Override
+        public boolean isUsable(final InteractionContext authentication, final 
Identifier identifier) {
+            return true;
+        }
+
+    }
+
+
+
+    @RegisterExtension
+    static GreenMailExtension greenMail = new 
GreenMailExtension(ServerSetupTest.SMTP)
+            
.withConfiguration(GreenMailConfiguration.aConfig().withUser("user", "admin"))
+            .withPerMethodLifecycle(false);
+
+    @Autowired
+    private EmailServiceDefault emailService;
+
+    @Test
+    void should_send_email_to_user_with_green_mail_extension() throws 
JSONException, MessagingException {
+
+        boolean send = emailService.send(Arrays.asList("[email protected]"), 
Collections.emptyList(), Collections.emptyList(), "Hello subject", "Hello 
word");
+
+        org.assertj.core.api.Assertions.assertThat(send).isTrue();
+
+        MimeMessage receivedMessage = greenMail.getReceivedMessages()[0];
+
+        Assertions.assertEquals(1, receivedMessage.getAllRecipients().length);
+
+        Assertions.assertEquals("[email protected]", 
receivedMessage.getAllRecipients()[0].toString());
+        Assertions.assertEquals("[email protected]", 
receivedMessage.getFrom()[0].toString());
+        Assertions.assertEquals("Message from Java Mail Sender", 
receivedMessage.getSubject());
+        Assertions.assertEquals("Hello this is a simple email message", 
GreenMailUtil.getBody(receivedMessage));
+    }
+
+}
\ No newline at end of file
diff --git a/core/runtimeservices/src/test/resources/application.yml 
b/core/runtimeservices/src/test/resources/application.yml
new file mode 100644
index 0000000000..737814cd91
--- /dev/null
+++ b/core/runtimeservices/src/test/resources/application.yml
@@ -0,0 +1,16 @@
+spring:
+  mail:
+    username: user
+    password: admin
+    host: 127.0.0.1
+    port: 3025
+    protocol: smtp
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+
+debug: true
+
diff --git a/core/security/src/main/java/module-info.java 
b/core/security/src/main/java/module-info.java
index 8a2e34aaa7..439b99620f 100644
--- a/core/security/src/main/java/module-info.java
+++ b/core/security/src/main/java/module-info.java
@@ -43,4 +43,6 @@ module org.apache.causeway.security.api {
     requires spring.core;
     requires spring.tx;
     requires org.apache.causeway.core.config;
+
+    opens org.apache.causeway.core.security to spring.core;
 }
\ No newline at end of file
diff --git a/core/transaction/src/main/java/module-info.java 
b/core/transaction/src/main/java/module-info.java
index bec887b514..88b6220a09 100644
--- a/core/transaction/src/main/java/module-info.java
+++ b/core/transaction/src/main/java/module-info.java
@@ -36,4 +36,8 @@ module org.apache.causeway.core.transaction {
     requires spring.core;
     requires spring.tx;
     requires java.transaction;
+
+    opens org.apache.causeway.core.transaction to spring.core;
+    opens org.apache.causeway.core.transaction.changetracking.events to 
spring.core;
+    opens org.apache.causeway.core.transaction.scope to spring.core;
 }
diff --git a/incubator/viewers/graphql/test/pom.xml 
b/incubator/viewers/graphql/test/pom.xml
index edb1462b46..0a0de9d84c 100644
--- a/incubator/viewers/graphql/test/pom.xml
+++ b/incubator/viewers/graphql/test/pom.xml
@@ -100,5 +100,4 @@
 
        </dependencies>
 
-
 </project>
diff --git a/valuetypes/jodatime/integration/src/main/java/module-info.java 
b/valuetypes/jodatime/integration/src/main/java/module-info.java
index 49ebe0438b..ed395d1dec 100644
--- a/valuetypes/jodatime/integration/src/main/java/module-info.java
+++ b/valuetypes/jodatime/integration/src/main/java/module-info.java
@@ -31,5 +31,6 @@ module org.apache.causeway.valuetypes.jodatime.integration {
     requires org.joda.time;
     requires spring.context;
 
-    opens org.apache.causeway.valuetypes.jodatime.integration.valuesemantics 
to org.apache.causeway.commons;
+    opens org.apache.causeway.valuetypes.jodatime.integration to spring.core;
+    opens org.apache.causeway.valuetypes.jodatime.integration.valuesemantics 
to spring.core, org.apache.causeway.commons;
 }
\ No newline at end of file


Reply via email to