Skip to content

Commit fe5044d

Browse files
author
Pritham Marupaka
committed
Add AbstractServiceError
1 parent 1bec06a commit fe5044d

File tree

7 files changed

+115
-11
lines changed

7 files changed

+115
-11
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* (c) Copyright 2025 Palantir Technologies Inc. All rights reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.palantir.conjure.java.api.errors;
18+
19+
import com.palantir.logsafe.SafeLoggable;
20+
21+
/**
22+
* This class should not be used directly. The parent class for ServiceException and EndpointServiceException.
23+
*/
24+
public abstract class AbstractServiceError extends RuntimeException implements SafeLoggable {
25+
public abstract ErrorType getErrorType();
26+
27+
protected AbstractServiceError(Throwable cause) {
28+
super(cause);
29+
}
30+
}

errors/src/main/java/com/palantir/conjure/java/api/errors/EndpointServiceException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717
package com.palantir.conjure.java.api.errors;
1818

1919
import com.palantir.logsafe.Arg;
20-
import com.palantir.logsafe.SafeLoggable;
2120
import java.util.List;
2221
import javax.annotation.Nullable;
2322

2423
/*
2524
* This is identical to ServiceException, but is used in Conjure-generated code to indicate that an exception was thrown
2625
* from a service endpoint.
2726
*/
28-
public abstract class EndpointServiceException extends RuntimeException implements SafeLoggable {
27+
public abstract class EndpointServiceException extends AbstractServiceError {
2928
private static final String EXCEPTION_NAME = "EndpointServiceException";
3029
private final ErrorType errorType;
3130
private final List<Arg<?>> args; // This is an unmodifiable list.
@@ -52,6 +51,7 @@ public EndpointServiceException(ErrorType errorType, @Nullable Throwable cause,
5251
}
5352

5453
/** The {@link ErrorType} that gave rise to this exception. */
54+
@Override
5555
public final ErrorType getErrorType() {
5656
return errorType;
5757
}

errors/src/main/java/com/palantir/conjure/java/api/errors/ServiceException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@
1717
package com.palantir.conjure.java.api.errors;
1818

1919
import com.palantir.logsafe.Arg;
20-
import com.palantir.logsafe.SafeLoggable;
2120
import java.util.List;
2221
import javax.annotation.Nullable;
2322

2423
/** A {@link ServiceException} thrown in server-side code to indicate server-side {@link ErrorType error states}. */
25-
public final class ServiceException extends RuntimeException implements SafeLoggable {
24+
public final class ServiceException extends AbstractServiceError {
2625
private static final String EXCEPTION_NAME = "ServiceException";
2726
private final ErrorType errorType;
2827
private final List<Arg<?>> args; // unmodifiable
@@ -53,6 +52,7 @@ public ServiceException(ErrorType errorType, @Nullable Throwable cause, Arg<?>..
5352
}
5453

5554
/** The {@link ErrorType} that gave rise to this exception. */
55+
@Override
5656
public ErrorType getErrorType() {
5757
return errorType;
5858
}

test-utils/src/main/java/com/palantir/conjure/java/api/testing/Assertions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.palantir.conjure.java.api.testing;
1818

19+
import com.palantir.conjure.java.api.errors.EndpointServiceException;
1920
import com.palantir.conjure.java.api.errors.QosException;
2021
import com.palantir.conjure.java.api.errors.RemoteException;
2122
import com.palantir.conjure.java.api.errors.ServiceException;
@@ -32,6 +33,10 @@ public static ServiceExceptionAssert assertThat(ServiceException actual) {
3233
return new ServiceExceptionAssert(actual);
3334
}
3435

36+
public static ServiceExceptionAssert assertThat(EndpointServiceException actual) {
37+
return new ServiceExceptionAssert(actual);
38+
}
39+
3540
public static RemoteExceptionAssert assertThat(RemoteException actual) {
3641
return new RemoteExceptionAssert(actual);
3742
}

test-utils/src/main/java/com/palantir/conjure/java/api/testing/ServiceExceptionAssert.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
package com.palantir.conjure.java.api.testing;
1818

19+
import com.palantir.conjure.java.api.errors.AbstractServiceError;
1920
import com.palantir.conjure.java.api.errors.ErrorType;
20-
import com.palantir.conjure.java.api.errors.ServiceException;
2121
import com.palantir.logsafe.Arg;
2222
import java.util.Arrays;
2323
import java.util.HashMap;
@@ -28,16 +28,17 @@
2828
import org.assertj.core.api.InstanceOfAssertFactory;
2929
import org.assertj.core.util.Throwables;
3030

31-
public class ServiceExceptionAssert extends AbstractThrowableAssert<ServiceExceptionAssert, ServiceException> {
31+
public class ServiceExceptionAssert extends AbstractThrowableAssert<ServiceExceptionAssert, AbstractServiceError> {
3232

33-
private static final InstanceOfAssertFactory<ServiceException, ServiceExceptionAssert> INSTANCE_OF_ASSERT_FACTORY =
34-
new InstanceOfAssertFactory<>(ServiceException.class, ServiceExceptionAssert::new);
33+
private static final InstanceOfAssertFactory<AbstractServiceError, ServiceExceptionAssert>
34+
INSTANCE_OF_ASSERT_FACTORY =
35+
new InstanceOfAssertFactory<>(AbstractServiceError.class, ServiceExceptionAssert::new);
3536

36-
ServiceExceptionAssert(ServiceException actual) {
37+
ServiceExceptionAssert(AbstractServiceError actual) {
3738
super(actual, ServiceExceptionAssert.class);
3839
}
3940

40-
public static InstanceOfAssertFactory<ServiceException, ServiceExceptionAssert> instanceOfAssertFactory() {
41+
public static InstanceOfAssertFactory<AbstractServiceError, ServiceExceptionAssert> instanceOfAssertFactory() {
4142
return INSTANCE_OF_ASSERT_FACTORY;
4243
}
4344

test-utils/src/test/java/com/palantir/conjure/java/api/testing/AssertionsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void testAssertThatServiceExceptionThrownBy_failsIfWrongExceptionThrown()
4545
throw new RuntimeException("My message");
4646
}))
4747
.hasMessageContaining(
48-
"com.palantir.conjure.java.api.errors.ServiceException",
48+
"com.palantir.conjure.java.api.errors.AbstractServiceError",
4949
"java.lang.RuntimeException",
5050
"My message");
5151
}

test-utils/src/test/java/com/palantir/conjure/java/api/testing/ServiceExceptionAssertTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,22 @@
1818

1919
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2020

21+
import com.palantir.conjure.java.api.errors.EndpointServiceException;
2122
import com.palantir.conjure.java.api.errors.ErrorType;
2223
import com.palantir.conjure.java.api.errors.ServiceException;
24+
import com.palantir.logsafe.Arg;
2325
import com.palantir.logsafe.SafeArg;
2426
import com.palantir.logsafe.UnsafeArg;
2527
import org.junit.jupiter.api.Test;
2628

2729
public class ServiceExceptionAssertTest {
2830

31+
private static class TestEndpointServiceException extends EndpointServiceException {
32+
TestEndpointServiceException(ErrorType errorType, Arg<?>... safeArgs) {
33+
super(errorType, safeArgs);
34+
}
35+
}
36+
2937
@Test
3038
public void testSanity() {
3139
ErrorType actualType = ErrorType.FAILED_PRECONDITION;
@@ -35,63 +43,123 @@ public void testSanity() {
3543
.hasType(actualType)
3644
.hasArgs(SafeArg.of("a", "b"), UnsafeArg.of("c", "d"));
3745

46+
Assertions.assertThat(
47+
new TestEndpointServiceException(actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
48+
.hasCode(actualType.code())
49+
.hasType(actualType)
50+
.hasArgs(SafeArg.of("a", "b"), UnsafeArg.of("c", "d"));
51+
3852
Assertions.assertThat(new ServiceException(actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
3953
.hasCode(actualType.code())
4054
.hasType(actualType)
4155
.hasArgs(UnsafeArg.of("c", "d"), SafeArg.of("a", "b")); // Order doesn't matter
4256

57+
Assertions.assertThat(
58+
new TestEndpointServiceException(actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
59+
.hasCode(actualType.code())
60+
.hasType(actualType)
61+
.hasArgs(UnsafeArg.of("c", "d"), SafeArg.of("a", "b")); // Order doesn't matter
62+
4363
Assertions.assertThat(new ServiceException(actualType)).hasNoArgs();
64+
Assertions.assertThat(new TestEndpointServiceException(actualType)).hasNoArgs();
4465

4566
assertThatThrownBy(() ->
4667
Assertions.assertThat(new ServiceException(actualType)).hasCode(ErrorType.Code.INTERNAL))
4768
.isInstanceOf(AssertionError.class)
4869
.hasMessageContaining(
4970
"Expected ErrorType.Code to be %s, but found %s", ErrorType.Code.INTERNAL, actualType.code());
71+
assertThatThrownBy(() -> Assertions.assertThat(new TestEndpointServiceException(actualType))
72+
.hasCode(ErrorType.Code.INTERNAL))
73+
.isInstanceOf(AssertionError.class)
74+
.hasMessageContaining(
75+
"Expected ErrorType.Code to be %s, but found %s", ErrorType.Code.INTERNAL, actualType.code());
5076

5177
assertThatThrownBy(() ->
5278
Assertions.assertThat(new ServiceException(actualType)).hasType(ErrorType.INTERNAL))
5379
.isInstanceOf(AssertionError.class)
5480
.hasMessageContaining("Expected ErrorType to be %s, but found %s", ErrorType.INTERNAL, actualType);
81+
assertThatThrownBy(() -> Assertions.assertThat(new TestEndpointServiceException(actualType))
82+
.hasType(ErrorType.INTERNAL))
83+
.isInstanceOf(AssertionError.class)
84+
.hasMessageContaining("Expected ErrorType to be %s, but found %s", ErrorType.INTERNAL, actualType);
5585

5686
assertThatThrownBy(() -> Assertions.assertThat(new ServiceException(actualType, SafeArg.of("a", "b")))
5787
.hasArgs(SafeArg.of("c", "d")))
5888
.isInstanceOf(AssertionError.class)
5989
.hasMessageContaining("Expected safe args to be {c=d}, but found {a=b}");
90+
assertThatThrownBy(
91+
() -> Assertions.assertThat(new TestEndpointServiceException(actualType, SafeArg.of("a", "b")))
92+
.hasArgs(SafeArg.of("c", "d")))
93+
.isInstanceOf(AssertionError.class)
94+
.hasMessageContaining("Expected safe args to be {c=d}, but found {a=b}");
6095

6196
assertThatThrownBy(() -> Assertions.assertThat(new ServiceException(actualType, UnsafeArg.of("a", "b")))
6297
.hasArgs(UnsafeArg.of("c", "d")))
6398
.isInstanceOf(AssertionError.class)
6499
.hasMessageContaining("Expected unsafe args to be {c=d}, but found {a=b}");
100+
assertThatThrownBy(() -> Assertions.assertThat(
101+
new TestEndpointServiceException(actualType, UnsafeArg.of("a", "b")))
102+
.hasArgs(UnsafeArg.of("c", "d")))
103+
.isInstanceOf(AssertionError.class)
104+
.hasMessageContaining("Expected unsafe args to be {c=d}, but found {a=b}");
65105

66106
assertThatThrownBy(() -> Assertions.assertThat(new ServiceException(actualType, SafeArg.of("a", "b")))
67107
.hasNoArgs())
68108
.isInstanceOf(AssertionError.class)
69109
.hasMessageContaining("Expected no args, but found {a=b}");
110+
assertThatThrownBy(
111+
() -> Assertions.assertThat(new TestEndpointServiceException(actualType, SafeArg.of("a", "b")))
112+
.hasNoArgs())
113+
.isInstanceOf(AssertionError.class)
114+
.hasMessageContaining("Expected no args, but found {a=b}");
70115

71116
assertThatThrownBy(() -> Assertions.assertThat(
72117
new ServiceException(actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
73118
.hasNoArgs())
74119
.isInstanceOf(AssertionError.class)
75120
.hasMessageContaining("Expected no args, but found {a=b, c=d}");
121+
assertThatThrownBy(() -> Assertions.assertThat(new TestEndpointServiceException(
122+
actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
123+
.hasNoArgs())
124+
.isInstanceOf(AssertionError.class)
125+
.hasMessageContaining("Expected no args, but found {a=b, c=d}");
76126

77127
Assertions.assertThat(new ServiceException(actualType, UnsafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
78128
.containsArgs(UnsafeArg.of("a", "b"));
129+
Assertions.assertThat(
130+
new TestEndpointServiceException(actualType, UnsafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
131+
.containsArgs(UnsafeArg.of("a", "b"));
79132

80133
// Safety matters
81134
assertThatThrownBy(() -> Assertions.assertThat(
82135
new ServiceException(actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
83136
.containsArgs(UnsafeArg.of("a", "b")))
84137
.isInstanceOf(AssertionError.class)
85138
.hasMessageContaining("Expected unsafe args to contain {a=b}, but found {c=d}");
139+
assertThatThrownBy(() -> Assertions.assertThat(new TestEndpointServiceException(
140+
actualType, SafeArg.of("a", "b"), UnsafeArg.of("c", "d")))
141+
.containsArgs(UnsafeArg.of("a", "b")))
142+
.isInstanceOf(AssertionError.class)
143+
.hasMessageContaining("Expected unsafe args to contain {a=b}, but found {c=d}");
86144

87145
assertThatThrownBy(() -> Assertions.assertThat(new ServiceException(actualType, SafeArg.of("a", "b")))
88146
.containsArgs(SafeArg.of("c", "d")))
89147
.isInstanceOf(AssertionError.class)
90148
.hasMessageContaining("Expected safe args to contain {c=d}, but found {a=b}");
149+
assertThatThrownBy(
150+
() -> Assertions.assertThat(new TestEndpointServiceException(actualType, SafeArg.of("a", "b")))
151+
.containsArgs(SafeArg.of("c", "d")))
152+
.isInstanceOf(AssertionError.class)
153+
.hasMessageContaining("Expected safe args to contain {c=d}, but found {a=b}");
91154

92155
assertThatThrownBy(() -> Assertions.assertThat(new ServiceException(actualType, UnsafeArg.of("a", "b")))
93156
.containsArgs(UnsafeArg.of("c", "d")))
94157
.isInstanceOf(AssertionError.class)
95158
.hasMessageContaining("Expected unsafe args to contain {c=d}, but found {a=b}");
159+
assertThatThrownBy(() -> Assertions.assertThat(
160+
new TestEndpointServiceException(actualType, UnsafeArg.of("a", "b")))
161+
.containsArgs(UnsafeArg.of("c", "d")))
162+
.isInstanceOf(AssertionError.class)
163+
.hasMessageContaining("Expected unsafe args to contain {c=d}, but found {a=b}");
96164
}
97165
}

0 commit comments

Comments
 (0)