Skip to content

Commit 909dbe2

Browse files
committed
Compile with Jakarta 9 and test with Jakarta 10
Also polishes. This ensures our instrumentation is compatible with Jakarta 9 and 10.
1 parent 748de21 commit 909dbe2

19 files changed

+225
-71
lines changed

Diff for: gradle/libs.versions.toml

-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ jacksonDatabind = { module = "com.fasterxml.jackson.core:jackson-databind", vers
134134
jakarta-annotationApi = { module = "jakarta.annotation:jakarta.annotation-api", version = "3.0.0" }
135135
jakarta-injectApi = { module = "jakarta.inject:jakarta.inject-api", version = "2.0.1" }
136136
jakarta-jmsApi = { module = "jakarta.jms:jakarta.jms-api", version = "3.0.0" }
137-
jakarta-mailApi = { module = "jakarta.mail:jakarta.mail-api", version = "2.1.3" }
138137
jakarta-servletApi = { module = "jakarta.servlet:jakarta.servlet-api", version = "5.0.0" }
139138
javalin = { module = "io.javalin:javalin", version = "5.6.5" }
140139
javax-cacheApi = { module = "javax.cache:cache-api", version.ref = "javax-cache" }

Diff for: micrometer-jakarta9/build.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ dependencies {
1919
api project(":micrometer-observation")
2020

2121
optionalApi 'jakarta.jms:jakarta.jms-api'
22-
optionalApi 'jakarta.mail:jakarta.mail-api:2.1.0'
22+
// Jakarta 9 version of the Mail API
23+
optionalApi 'jakarta.mail:jakarta.mail-api:2.0.1'
2324

2425
testImplementation(libs.archunitJunit5) {
2526
// avoid transitively pulling in slf4j 2
@@ -29,5 +30,5 @@ dependencies {
2930
testImplementation libs.mockitoCore5
3031
testImplementation project(':micrometer-observation-test')
3132
testImplementation 'org.assertj:assertj-core'
32-
testImplementation 'org.eclipse.angus:jakarta.mail:2.0.3'
33+
testRuntimeOnly('com.sun.mail:jakarta.mail:2.0.1')
3334
}

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/DefaultMailSendObservationConvention.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
2020

2121
/**
2222
* Default implementation for {@link MailSendObservationConvention}.
23+
*
24+
* @since 1.15.0
2325
*/
2426
public class DefaultMailSendObservationConvention implements MailSendObservationConvention {
2527

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/InstrumentedTransport.java

+28-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,23 +16,26 @@
1616
package io.micrometer.jakarta9.instrument.mail;
1717

1818
import io.micrometer.common.lang.Nullable;
19-
import io.micrometer.common.util.internal.logging.InternalLogger;
20-
import io.micrometer.common.util.internal.logging.InternalLoggerFactory;
2119
import io.micrometer.observation.Observation;
2220
import io.micrometer.observation.ObservationConvention;
2321
import io.micrometer.observation.ObservationRegistry;
2422
import jakarta.mail.*;
2523

24+
/**
25+
* Wraps a {@link Transport} so that it is instrumented with a Micrometer
26+
* {@link Observation}.
27+
*
28+
* @since 1.15.0
29+
*/
2630
public class InstrumentedTransport extends Transport {
2731

28-
private static final InternalLogger LOGGER = InternalLoggerFactory.getInstance(InstrumentedTransport.class);
32+
private static final DefaultMailSendObservationConvention DEFAULT_CONVENTION = new DefaultMailSendObservationConvention();
2933

30-
private static final ObservationConvention<MailSendObservationContext> DEFAULT_CONVENTION = new DefaultMailSendObservationConvention();
31-
32-
private ObservationRegistry observationRegistry;
34+
private final ObservationRegistry observationRegistry;
3335

3436
private final Transport delegate;
3537

38+
@Nullable
3639
private final String protocol;
3740

3841
@Nullable
@@ -43,14 +46,27 @@ public class InstrumentedTransport extends Transport {
4346

4447
private int port;
4548

46-
public InstrumentedTransport(Session session, Transport delegate, ObservationRegistry observationRegistry)
47-
throws NoSuchProviderException {
49+
/**
50+
* Create an instrumented transport using the
51+
* {@link DefaultMailSendObservationConvention default} {@link ObservationConvention}.
52+
* @param session session for the delegate transport
53+
* @param delegate transport to instrument
54+
* @param observationRegistry registry for the observations
55+
*/
56+
public InstrumentedTransport(Session session, Transport delegate, ObservationRegistry observationRegistry) {
4857
this(session, delegate, observationRegistry, null);
4958
}
5059

60+
/**
61+
* Create an instrumented transport with a custom {@link MailSendObservationConvention
62+
* convention}.
63+
* @param session session for the delegate transport
64+
* @param delegate transport to instrument
65+
* @param observationRegistry registry for the observations
66+
* @param customConvention override the convention to apply to the instrumentation
67+
*/
5168
public InstrumentedTransport(Session session, Transport delegate, ObservationRegistry observationRegistry,
52-
@Nullable ObservationConvention<MailSendObservationContext> customConvention)
53-
throws NoSuchProviderException {
69+
@Nullable ObservationConvention<MailSendObservationContext> customConvention) {
5470
super(session, delegate.getURLName());
5571
this.protocol = this.url.getProtocol();
5672
this.delegate = delegate;
@@ -73,7 +89,7 @@ public void sendMessage(Message msg, Address[] addresses) throws MessagingExcept
7389
observationRegistry);
7490

7591
observation.start();
76-
try (Observation.Scope scope = observation.openScope()) {
92+
try (Observation.Scope ignore = observation.openScope()) {
7793
// the Message-Id is set by the SMTP after sending the message
7894
this.delegate.sendMessage(msg, addresses);
7995
observation.highCardinalityKeyValue(MailKeyValues.smtpMessageId(msg));

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/MailKeyValues.java

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@
2626
import jakarta.mail.MessagingException;
2727
import jakarta.mail.Message.RecipientType;
2828

29-
public class MailKeyValues {
29+
class MailKeyValues {
3030

3131
private static final KeyValue SMTP_MESSAGE_FROM_UNKNOWN = KeyValue
3232
.of(MailObservationDocumentation.HighCardinalityKeyNames.SMTP_MESSAGE_FROM, "unknown");
@@ -106,13 +106,17 @@ static KeyValue smtpMessageId(Message message) {
106106
}
107107

108108
static KeyValue serverAddress(MailSendObservationContext context) {
109-
return KeyValue.of(LowCardinalityKeyNames.SERVER_ADDRESS,
110-
context.getHost() == null ? "unknown" : context.getHost());
109+
if (context.getHost() == null) {
110+
return SERVER_ADDRESS_UNKNOWN;
111+
}
112+
return KeyValue.of(LowCardinalityKeyNames.SERVER_ADDRESS, context.getHost());
111113
}
112114

113115
static KeyValue serverPort(MailSendObservationContext context) {
114-
return KeyValue.of(LowCardinalityKeyNames.SERVER_PORT,
115-
context.getPort() > 0 ? String.valueOf(context.getPort()) : "unknown");
116+
if (context.getPort() <= 0) {
117+
return SERVER_PORT_UNKNOWN;
118+
}
119+
return KeyValue.of(LowCardinalityKeyNames.SERVER_PORT, String.valueOf(context.getPort()));
116120
}
117121

118122
static KeyValue networkProtocolName(MailSendObservationContext context) {

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/MailObservationDocumentation.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
2323
/**
2424
* Documented {@link io.micrometer.common.KeyValue KeyValues} for the observations on
2525
* {@link jakarta.mail.Transport send} of mail messages.
26+
*
27+
* @since 1.15.0
2628
*/
2729
public enum MailObservationDocumentation implements ObservationDocumentation {
2830

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/MailSendObservationContext.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,21 +25,24 @@
2525
* Context that holds information for observation metadata collection during the
2626
* {@link MailObservationDocumentation#MAIL_SEND sending of mail messages}.
2727
* <p>
28-
* This propagates the tracing information with the message sent by
28+
* This propagates metadata with the message sent by
2929
* {@link Message#setHeader(String, String) setting a message header}.
30+
*
31+
* @since 1.15.0
3032
*/
3133
public class MailSendObservationContext extends SenderContext<Message> {
3234

3335
private static final WarnThenDebugLogger logger = new WarnThenDebugLogger(MailSendObservationContext.class);
3436

37+
@Nullable
3538
private final String protocol;
3639

3740
@Nullable
3841
private final String host;
3942

4043
private final int port;
4144

42-
public MailSendObservationContext(Message msg, String protocol, @Nullable String host, int port) {
45+
public MailSendObservationContext(Message msg, @Nullable String protocol, @Nullable String host, int port) {
4346
super((message, key, value) -> {
4447
if (message != null) {
4548
try {
@@ -56,6 +59,7 @@ public MailSendObservationContext(Message msg, String protocol, @Nullable String
5659
this.port = port;
5760
}
5861

62+
@Nullable
5963
public String getProtocol() {
6064
return protocol;
6165
}

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/MailSendObservationConvention.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,8 @@
2121
/**
2222
* {@link ObservationConvention} interface for
2323
* {@link MailObservationDocumentation#MAIL_SEND mail send} operations.
24+
*
25+
* @since 1.15.0
2426
*/
2527
public interface MailSendObservationConvention extends ObservationConvention<MailSendObservationContext> {
2628

Diff for: micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/mail/package-info.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616

1717
/**
1818
* Observation instrumentation for Jakarta Mail.
19+
*
20+
* @since 1.15.0
1921
*/
2022
@NonNullFields
2123
@NonNullApi

Diff for: micrometer-jakarta9/src/test/java/io/micrometer/jakarta9/instrument/mail/DefaultMailSendObservationConventionTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,63 +27,54 @@
2727
import static org.assertj.core.api.Assertions.assertThat;
2828

2929
import org.junit.jupiter.api.BeforeEach;
30-
import org.junit.jupiter.api.DisplayName;
3130
import org.junit.jupiter.api.Test;
3231
import org.mockito.Mockito;
3332

3433
import static org.mockito.Mockito.verify;
3534
import static org.mockito.Mockito.when;
3635

36+
/**
37+
* Tests for {@link InstrumentedTransport}.
38+
*/
3739
class InstrumentedTransportTest {
3840

39-
private Session session;
41+
Session session;
4042

41-
private MockSMTPTransportListener listener;
43+
MockSMTPTransportListener listener = Mockito.mock(MockSMTPTransportListener.class);
4244

43-
private TestObservationRegistry registry;
45+
TestObservationRegistry registry = TestObservationRegistry.create();
4446

45-
@BeforeEach
46-
void setUp() {
47-
this.listener = Mockito.mock(MockSMTPTransportListener.class);
48-
registry = TestObservationRegistry.create();
47+
Transport transport;
4948

49+
@BeforeEach
50+
void setUp() throws NoSuchProviderException {
5051
// prepare properties for the session
5152
Properties smtpProperties = new Properties();
5253
// default use of mock to simplify test
5354
smtpProperties.put("mail.transport.protocol", "mocksmtp");
5455

55-
// listen the mock
56+
// avoid NPE
5657
MockSMTPTransport.LISTENER = listener;
5758

58-
// the class have to open a Session
59+
// open a Session
5960
this.session = Session.getInstance(smtpProperties);
60-
}
61-
62-
@DisplayName("Test mock SMTP transport setup.")
63-
@Test
64-
void shouldConstructDelegatedTransport() throws NoSuchProviderException {
65-
Transport transport = this.session.getTransport("mocksmtp");
66-
assertThat(transport).isInstanceOf(MockSMTPTransport.class);
67-
verify(listener).onConstructor(this.session, new URLName("mocksmtp:"));
61+
transport = new InstrumentedTransport(session, this.session.getTransport("mocksmtp"), this.registry);
6862
}
6963

7064
@Test
7165
void shouldDelegateConnect() throws MessagingException {
72-
Transport transport = new InstrumentedTransport(session, this.session.getTransport("mocksmtp"), this.registry);
7366
transport.connect("host", 123, "user", "password");
7467
verify(listener).onConnect("host", 123, "user", "password");
7568
}
7669

7770
@Test
7871
void shouldDelegateClose() throws MessagingException {
79-
Transport transport = new InstrumentedTransport(session, this.session.getTransport("mocksmtp"), this.registry);
8072
transport.close();
8173
verify(listener).onClose();
8274
}
8375

8476
@Test
8577
void shouldDelegateSendMessageEvenIfObservationRegistryIsNotInstalled() throws MessagingException {
86-
Transport transport = new InstrumentedTransport(session, this.session.getTransport("mocksmtp"), this.registry);
8778
Message msg = new MimeMessage(this.session);
8879
Address[] to = new Address[0];
8980
transport.sendMessage(msg, to);
@@ -92,7 +83,6 @@ void shouldDelegateSendMessageEvenIfObservationRegistryIsNotInstalled() throws M
9283

9384
@Test
9485
void shouldDelegateSendMessageIfObservationRegistryIsInstalled() throws MessagingException {
95-
Transport transport = new InstrumentedTransport(session, this.session.getTransport("mocksmtp"), this.registry);
9686
Message msg = new MimeMessage(this.session);
9787
Address[] to = new Address[0];
9888
transport.sendMessage(msg, to);
@@ -107,7 +97,6 @@ void shouldCreateObservationWhenSendMessageIsCalled() throws MessagingException
10797
message.setHeader("Message-Id", "message-id");
10898
return true;
10999
});
110-
Transport transport = new InstrumentedTransport(session, this.session.getTransport("mocksmtp"), this.registry);
111100
Message msg = new MimeMessage(this.session);
112101
msg.setSubject("Hello world");
113102
Address[] to = new Address[0];
@@ -119,17 +108,17 @@ void shouldCreateObservationWhenSendMessageIsCalled() throws MessagingException
119108
transport.sendMessage(msg, to);
120109

121110
// assert
122-
assertThat(registry).hasAnObservation(observationContextAssert -> {
123-
observationContextAssert.hasNameEqualTo("mail.send");
124-
observationContextAssert.hasHighCardinalityKeyValue("smtp.message.id", "message-id");
125-
observationContextAssert.hasHighCardinalityKeyValue("smtp.message.subject", "Hello world");
126-
observationContextAssert.hasHighCardinalityKeyValue("smtp.message.to", "[email protected]");
127-
observationContextAssert.hasHighCardinalityKeyValue("smtp.message.from", "[email protected]");
128-
129-
observationContextAssert.hasLowCardinalityKeyValue("server.address", "example.com");
130-
observationContextAssert.hasLowCardinalityKeyValue("server.port", "123");
131-
observationContextAssert.hasLowCardinalityKeyValue("network.protocol.name", "mocksmtp");
132-
});
111+
assertThat(registry).hasObservationWithNameEqualTo("mail.send")
112+
.that()
113+
.hasBeenStarted()
114+
.hasBeenStopped()
115+
.hasHighCardinalityKeyValue("smtp.message.id", "message-id")
116+
.hasHighCardinalityKeyValue("smtp.message.subject", "Hello world")
117+
.hasHighCardinalityKeyValue("smtp.message.to", "[email protected]")
118+
.hasHighCardinalityKeyValue("smtp.message.from", "from@example.com")
119+
.hasLowCardinalityKeyValue("server.address", "example.com")
120+
.hasLowCardinalityKeyValue("server.port", "123")
121+
.hasLowCardinalityKeyValue("network.protocol.name", "mocksmtp");
133122
}
134123

135124
}

Diff for: micrometer-jakarta9/src/test/java/io/micrometer/jakarta9/instrument/mail/MailObservationDocumentationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 VMware, Inc.
2+
* Copyright 2025 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)