Skip to content

Commit

Permalink
Support an alias for a bunch of annotations (line#1560)
Browse files Browse the repository at this point in the history
Motivation:
A user may want to define his or her annotations as a custom annotation in order to apply the custom annotation to his or her annotated HTTP services. e.g:
```
// Define a custom annotation:
@ProducesJson
@LoggingDecorator
@interface MyApiSpecification {}

// Apply it to the annotated HTTP service:
@get("/api")
@MyApiSpecification
public Something getSomething() {}
```

Modifications:
- Add `AnnotationUtil` for finding a specific annotation or getting all annotations from an `AnnotatedElement`.
- Use `AnnotationUtil` instead of `ReflectionUtils.getAllAnnotations()`. The old one does not respect the order of the annotations because its return type is a `Set<Annotation>` (more specifically it's `HashSet`).

Result:
- Won't depend on the `ReflectionUtils`'s implementation when getting annotations.
  • Loading branch information
hyangtack authored and trustin committed Jan 31, 2019
1 parent 5d85883 commit 9f76e88
Show file tree
Hide file tree
Showing 9 changed files with 1,199 additions and 193 deletions.
5 changes: 5 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ This product depends on Caffeine, distributed by Ben Manes:
* License: licenses/LICENSE.caffeine.al20.txt (Apache License v2.0)
* Homepage: https://github.com/ben-manes/caffeine

This product depends on cglib, distributed by the cglib authors:

* License: licenses/LICENSE.cglib.al20.txt (Apache License v2.0)
* Homepage: https://github.com/cglib/cglib

This product depends on completable-futures, distributed by Spotify AB:

* License: license/LICENSE.completable-futures.al20.txt (Apache License v2.0)
Expand Down
3 changes: 3 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
dependencies {
// cglib
testCompile 'cglib:cglib'

// Caffeine
compile 'com.github.ben-manes.caffeine:caffeine'

Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2019 LINE Corporation
*
* LINE Corporation 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:
*
* https://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 com.linecorp.armeria.internal.annotation;

import static org.assertj.core.api.Assertions.assertThat;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.annotation.Nullable;

import org.junit.ClassRule;
import org.junit.Test;

import com.linecorp.armeria.client.HttpClient;
import com.linecorp.armeria.common.AggregatedHttpMessage;
import com.linecorp.armeria.common.HttpData;
import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.HttpStatus;
import com.linecorp.armeria.common.MediaType;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.annotation.Get;
import com.linecorp.armeria.server.annotation.Param;
import com.linecorp.armeria.server.annotation.Produces;
import com.linecorp.armeria.server.annotation.ResponseConverter;
import com.linecorp.armeria.server.annotation.ResponseConverterFunction;
import com.linecorp.armeria.testing.server.ServerRule;

public class AnnotatedHttpServiceAnnotationAliasTest {

@Retention(RetentionPolicy.RUNTIME)
@ResponseConverter(MyResponseConverter.class)
@Produces("text/plain")
@interface MyResponse {}

static class MyResponseConverter implements ResponseConverterFunction {
@Override
public HttpResponse convertResponse(ServiceRequestContext ctx, HttpHeaders headers,
@Nullable Object result, HttpHeaders trailingHeaders)
throws Exception {
return HttpResponse.of(
headers, HttpData.ofUtf8("Hello, %s!", result), trailingHeaders);
}
}

@ClassRule
public static ServerRule rule = new ServerRule() {
@Override
protected void configure(ServerBuilder sb) throws Exception {
sb.annotatedService(new Object() {
@Get("/hello/{name}")
@MyResponse
public String name(@Param String name) {
return name;
}
});
}
};

@Test
public void serviceConfiguredWithAlias() {
final AggregatedHttpMessage msg = HttpClient.of(rule.uri("/")).get("/hello/Armeria")
.aggregate().join();
assertThat(msg.status()).isEqualTo(HttpStatus.OK);
assertThat(msg.headers().contentType()).isEqualTo(MediaType.parse("text/plain"));
assertThat(msg.content().toStringUtf8()).isEqualTo("Hello, Armeria!");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ public void cancel() {

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Produces("application/binary")
@Produces("application/octet-stream")
@interface UserProduceBinary {}

Expand Down

0 comments on commit 9f76e88

Please sign in to comment.