> response = githubApi.contributors("square", "retrofit").execute();
48 | System.out.println(response);
49 | ```
50 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-autoconfigure/src/main/java/com/mnazareno/retrofit/springboot/DefaultRetrofitClientConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2016 the original author or authors.
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.mnazareno.retrofit.springboot;
18 |
19 | import com.fasterxml.jackson.databind.DeserializationFeature;
20 | import com.fasterxml.jackson.databind.ObjectMapper;
21 | import org.springframework.beans.factory.annotation.Autowired;
22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
23 | import org.springframework.context.annotation.Bean;
24 | import org.springframework.context.annotation.Configuration;
25 | import retrofit2.Converter;
26 | import retrofit2.converter.jackson.JacksonConverterFactory;
27 |
28 | @Configuration
29 | public class DefaultRetrofitClientConfiguration {
30 |
31 | @Bean
32 | @Autowired
33 | public Converter.Factory jacksonConverter(ObjectMapper objectMapper) {
34 | return JacksonConverterFactory.create(objectMapper);
35 | }
36 |
37 | @Bean
38 | @ConditionalOnMissingBean
39 | public ObjectMapper objectMapper() {
40 | ObjectMapper om = new ObjectMapper();
41 | om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
42 | return om;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-starter-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.mnazareno
8 | retrofit-spring-boot-starter-demo
9 | 0.0.1-SNAPSHOT
10 | jar
11 |
12 | retrofit-spring-boot-starter-demo
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-parent
18 | 1.5.9.RELEASE
19 |
20 |
21 |
22 |
23 | UTF-8
24 | UTF-8
25 | 1.8
26 |
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter
32 |
33 |
34 | com.mnazareno
35 | retrofit-spring-boot-starter
36 | 1.0-SNAPSHOT
37 |
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-test
42 | test
43 |
44 |
45 |
46 |
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-maven-plugin
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-autoconfigure/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | retrofit-spring-boot
7 | com.mnazareno
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | retrofit-spring-boot-autoconfigure
13 |
14 |
15 |
16 | org.apache.maven.plugins
17 | maven-compiler-plugin
18 |
19 | 1.8
20 | 1.8
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | com.squareup.retrofit2
29 | retrofit
30 |
31 |
32 | com.squareup.retrofit2
33 | converter-jackson
34 |
35 |
36 | com.squareup.okhttp3
37 | logging-interceptor
38 |
39 |
40 | org.springframework
41 | spring-context
42 |
43 |
44 | org.springframework.cloud
45 | spring-cloud-context
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-autoconfigure
50 | 1.5.9.RELEASE
51 |
52 |
53 | org.projectlombok
54 | lombok
55 | 1.16.20
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.mnazareno
8 | retrofit-spring-boot
9 | 1.0-SNAPSHOT
10 |
11 | retrofit-spring-boot-autoconfigure
12 | retrofit-spring-boot-starter
13 | retrofit-spring-boot-starter-demo
14 |
15 | pom
16 |
17 |
18 | 4.3.13.RELEASE
19 | 2.3.0
20 | 3.9.1
21 | 1.3.1.RELEASE
22 |
23 |
24 |
25 |
26 |
27 | org.springframework
28 | spring-context
29 | 4.3.13.RELEASE
30 |
31 |
32 | org.springframework.cloud
33 | spring-cloud-context
34 | ${spring-cloud-context.version}
35 |
36 |
37 | com.squareup.retrofit2
38 | retrofit
39 | ${retrofit.version}
40 |
41 |
42 | com.squareup.retrofit2
43 | converter-jackson
44 | ${retrofit.version}
45 |
46 |
47 | com.squareup.okhttp3
48 | logging-interceptor
49 | ${okhttp.version}
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-autoconfigure/src/main/java/com/mnazareno/retrofit/springboot/RetrofitClientFactoryBean.java:
--------------------------------------------------------------------------------
1 | package com.mnazareno.retrofit.springboot;
2 |
3 | import java.util.Optional;
4 |
5 | import org.springframework.beans.BeansException;
6 | import org.springframework.beans.factory.FactoryBean;
7 | import org.springframework.beans.factory.InitializingBean;
8 | import org.springframework.context.ApplicationContext;
9 | import org.springframework.context.ApplicationContextAware;
10 |
11 | import lombok.Data;
12 | import okhttp3.OkHttpClient;
13 | import retrofit2.CallAdapter;
14 | import retrofit2.Converter;
15 | import retrofit2.Retrofit;
16 |
17 | @Data
18 | public class RetrofitClientFactoryBean
19 | implements FactoryBean, ApplicationContextAware, InitializingBean {
20 |
21 | private Class> type;
22 |
23 | private String name;
24 |
25 | private String baseUrl;
26 |
27 | private ApplicationContext ctx;
28 |
29 | public RetrofitClientFactoryBean() {
30 | }
31 |
32 | @Override
33 | public Object getObject() throws Exception {
34 | RetrofitClientContext retrofitClientContext = this.ctx
35 | .getBean(RetrofitClientContext.class);
36 |
37 | Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
38 | retrofitBuilder.baseUrl(this.baseUrl);
39 |
40 | OkHttpClient okHttpClient = Optional
41 | .ofNullable(
42 | retrofitClientContext.getInstance(this.name, OkHttpClient.class))
43 | .orElse(new OkHttpClient());
44 | retrofitBuilder.client(okHttpClient);
45 |
46 | Optional.ofNullable(
47 | retrofitClientContext.getInstances(this.name, Converter.Factory.class))
48 | .ifPresent(a -> a.values().forEach(retrofitBuilder::addConverterFactory));
49 |
50 | Optional.ofNullable(
51 | retrofitClientContext.getInstances(this.name, CallAdapter.Factory.class))
52 | .ifPresent(instances -> instances.values()
53 | .forEach(retrofitBuilder::addCallAdapterFactory));
54 |
55 | return retrofitBuilder.build().create(this.type);
56 | }
57 |
58 | @Override
59 | public Class> getObjectType() {
60 | return this.type;
61 | }
62 |
63 | @Override
64 | public boolean isSingleton() {
65 | return true;
66 | }
67 |
68 | @Override
69 | public void afterPropertiesSet() throws Exception {
70 | }
71 |
72 | @Override
73 | public void setApplicationContext(ApplicationContext applicationContext)
74 | throws BeansException {
75 | this.ctx = applicationContext;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-autoconfigure/src/main/java/com/mnazareno/retrofit/springboot/EnableRetrofitClients.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2015 the original author or authors.
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.mnazareno.retrofit.springboot;
18 |
19 | import java.lang.annotation.*;
20 |
21 | import org.springframework.context.annotation.Import;
22 |
23 | /**
24 | * Scans for interfaces that declare they are clients (via {@link RetrofitClient
25 | * @RetrofitClient}). Configures component scanning directives for use with
26 | * {@link org.springframework.context.annotation.Configuration
27 | * @Configuration} classes.
28 | *
29 | * @author Spencer Gibb
30 | * @author Dave Syer
31 | * @since 1.0
32 | */
33 | @Retention(RetentionPolicy.RUNTIME)
34 | @Target(ElementType.TYPE)
35 | @Documented
36 | @Import(RetrofitClientsRegistrar.class)
37 | public @interface EnableRetrofitClients {
38 |
39 | /**
40 | * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
41 | * declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
42 | * {@code @ComponentScan(basePackages="org.my.pkg")}.
43 | *
44 | * @return the array of 'basePackages'.
45 | */
46 | String[] value() default {};
47 |
48 | /**
49 | * Base packages to scan for annotated components.
50 | *
51 | *
52 | * {@link #value()} is an alias for (and mutually exclusive with) this attribute.
53 | *
54 | *
55 | * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
56 | * package names.
57 | *
58 | * @return the array of 'basePackages'.
59 | */
60 | String[] basePackages() default {};
61 |
62 | /**
63 | * Type-safe alternative to {@link #basePackages()} for specifying the packages to
64 | * scan for annotated components. The package of each class specified will be scanned.
65 | *
66 | *
67 | * Consider creating a special no-op marker class or interface in each package that
68 | * serves no purpose other than being referenced by this attribute.
69 | *
70 | * @return the array of 'basePackageClasses'.
71 | */
72 | Class>[] basePackageClasses() default {};
73 |
74 | /**
75 | * A custom @Configuration for all clients. Can contain override
76 | * @Bean definition for the pieces that make up the client.
77 | *
78 | * @see DefaultRetrofitClientConfiguration for the defaults
79 | */
80 | Class>[] defaultConfiguration() default {};
81 |
82 | /**
83 | * List of classes annotated with @RetrofitClient. If not empty, disables classpath
84 | * scanning.
85 | */
86 | Class>[] clients() default {};
87 | }
88 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-starter/retrofit-spring-boot-starter.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-autoconfigure/retrofit-spring-boot-autoconfigure.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | file://$MODULE_DIR$/src/main/java/com/mnazareno/retrofit/springboot/DefaultRetrofitClientConfiguration.java
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Windows template
3 | # Windows thumbnail cache files
4 | Thumbs.db
5 | ehthumbs.db
6 | ehthumbs_vista.db
7 |
8 | # Dump file
9 | *.stackdump
10 |
11 | # Folder config file
12 | [Dd]esktop.ini
13 |
14 | # Recycle Bin used on file shares
15 | $RECYCLE.BIN/
16 |
17 | # Windows Installer files
18 | *.cab
19 | *.msi
20 | *.msm
21 | *.msp
22 |
23 | # Windows shortcuts
24 | *.lnk
25 | ### Java template
26 | # Compiled class file
27 | *.class
28 |
29 | # Log file
30 | *.log
31 |
32 | # BlueJ files
33 | *.ctxt
34 |
35 | # Mobile Tools for Java (J2ME)
36 | .mtj.tmp/
37 |
38 | # Package Files #
39 | *.jar
40 | *.war
41 | *.ear
42 | *.zip
43 | *.tar.gz
44 | *.rar
45 |
46 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
47 | hs_err_pid*
48 | ### Eclipse template
49 |
50 | .metadata
51 | bin/
52 | tmp/
53 | *.tmp
54 | *.bak
55 | *.swp
56 | *~.nib
57 | local.properties
58 | .settings/
59 | .loadpath
60 | .recommenders
61 |
62 | # External tool builders
63 | .externalToolBuilders/
64 |
65 | # Locally stored "Eclipse launch configurations"
66 | *.launch
67 |
68 | # PyDev specific (Python IDE for Eclipse)
69 | *.pydevproject
70 |
71 | # CDT-specific (C/C++ Development Tooling)
72 | .cproject
73 |
74 | # CDT- autotools
75 | .autotools
76 |
77 | # Java annotation processor (APT)
78 | .factorypath
79 |
80 | # PDT-specific (PHP Development Tools)
81 | .buildpath
82 |
83 | # sbteclipse plugin
84 | .target
85 |
86 | # Tern plugin
87 | .tern-project
88 |
89 | # TeXlipse plugin
90 | .texlipse
91 |
92 | # STS (Spring Tool Suite)
93 | .springBeans
94 |
95 | # Code Recommenders
96 | .recommenders/
97 |
98 | # Scala IDE specific (Scala & Java development for Eclipse)
99 | .cache-main
100 | .scala_dependencies
101 | .worksheet
102 | ### macOS template
103 | # General
104 | .DS_Store
105 | .AppleDouble
106 | .LSOverride
107 |
108 | # Icon must end with two \r
109 | Icon
110 |
111 | # Thumbnails
112 | ._*
113 |
114 | # Files that might appear in the root of a volume
115 | .DocumentRevisions-V100
116 | .fseventsd
117 | .Spotlight-V100
118 | .TemporaryItems
119 | .Trashes
120 | .VolumeIcon.icns
121 | .com.apple.timemachine.donotpresent
122 |
123 | # Directories potentially created on remote AFP share
124 | .AppleDB
125 | .AppleDesktop
126 | Network Trash Folder
127 | Temporary Items
128 | .apdisk
129 | ### JetBrains template
130 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
131 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
132 |
133 | # User-specific stuff:
134 | .idea/**/workspace.xml
135 | .idea/**/tasks.xml
136 | .idea/dictionaries
137 |
138 | # Sensitive or high-churn files:
139 | .idea/**/dataSources/
140 | .idea/**/dataSources.ids
141 | .idea/**/dataSources.xml
142 | .idea/**/dataSources.local.xml
143 | .idea/**/sqlDataSources.xml
144 | .idea/**/dynamic.xml
145 | .idea/**/uiDesigner.xml
146 |
147 | # Gradle:
148 | .idea/**/gradle.xml
149 | .idea/**/libraries
150 |
151 | # CMake
152 | cmake-build-debug/
153 | cmake-build-release/
154 |
155 | # Mongo Explorer plugin:
156 | .idea/**/mongoSettings.xml
157 |
158 | ## File-based project format:
159 | *.iws
160 |
161 | ## Plugin-specific files:
162 |
163 | # IntelliJ
164 | out/
165 |
166 | # mpeltonen/sbt-idea plugin
167 | .idea_modules/
168 |
169 | # JIRA plugin
170 | atlassian-ide-plugin.xml
171 |
172 | # Cursive Clojure plugin
173 | .idea/replstate.xml
174 |
175 | # Crashlytics plugin (for Android Studio and IntelliJ)
176 | com_crashlytics_export_strings.xml
177 | crashlytics.properties
178 | crashlytics-build.properties
179 | fabric.properties
180 |
181 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-autoconfigure/src/main/java/com/mnazareno/retrofit/springboot/RetrofitClientsRegistrar.java:
--------------------------------------------------------------------------------
1 | package com.mnazareno.retrofit.springboot;
2 |
3 | import java.util.HashSet;
4 | import java.util.Map;
5 | import java.util.Set;
6 |
7 | import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
8 | import org.springframework.beans.factory.support.BeanDefinitionBuilder;
9 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
10 | import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
11 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
12 | import org.springframework.core.type.AnnotationMetadata;
13 | import org.springframework.core.type.filter.AnnotationTypeFilter;
14 | import org.springframework.util.ClassUtils;
15 | import org.springframework.util.StringUtils;
16 |
17 | public class RetrofitClientsRegistrar implements ImportBeanDefinitionRegistrar {
18 |
19 | @Override
20 | public void registerBeanDefinitions(AnnotationMetadata metadata,
21 | BeanDefinitionRegistry registry) {
22 |
23 | ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(
24 | false) {
25 | @Override
26 | protected boolean isCandidateComponent(
27 | AnnotatedBeanDefinition beanDefinition) {
28 | return beanDefinition.getMetadata().isIndependent()
29 | && !beanDefinition.getMetadata().isAnnotation();
30 | }
31 | };
32 | scanner.addIncludeFilter(new AnnotationTypeFilter(RetrofitClient.class));
33 |
34 | Set basePackages = getBasePackages(metadata);
35 |
36 | basePackages.stream().map(scanner::findCandidateComponents).flatMap(Set::stream)
37 | .forEach(candidateComponent -> {
38 | AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
39 | Map attributes = beanDefinition.getMetadata()
40 | .getAnnotationAttributes(
41 | RetrofitClient.class.getCanonicalName());
42 | String name = attributes.get("name").toString();
43 |
44 | BeanDefinitionBuilder retrofitClientFactoryBeanBuilder = BeanDefinitionBuilder
45 | .genericBeanDefinition(RetrofitClientFactoryBean.class);
46 | retrofitClientFactoryBeanBuilder.addPropertyValue("type",
47 | beanDefinition.getBeanClassName());
48 | retrofitClientFactoryBeanBuilder.addPropertyValue("name", name);
49 | retrofitClientFactoryBeanBuilder.addPropertyValue("baseUrl",
50 | attributes.get("baseUrl"));
51 |
52 | registerClientConfiguration(registry, name,
53 | attributes.get("configuration"));
54 | registry.registerBeanDefinition(name,
55 | retrofitClientFactoryBeanBuilder.getBeanDefinition());
56 | });
57 | }
58 |
59 | private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
60 | Object configuration) {
61 | BeanDefinitionBuilder builder = BeanDefinitionBuilder
62 | .genericBeanDefinition(RetrofitClientSpecification.class);
63 | builder.addConstructorArgValue(name);
64 | builder.addConstructorArgValue(configuration);
65 | registry.registerBeanDefinition(
66 | name + "." + RetrofitClientSpecification.class.getSimpleName(),
67 | builder.getBeanDefinition());
68 | }
69 |
70 | protected Set getBasePackages(AnnotationMetadata importingClassMetadata) {
71 | Map attributes = importingClassMetadata
72 | .getAnnotationAttributes(EnableRetrofitClients.class.getCanonicalName());
73 |
74 | Set basePackages = new HashSet<>();
75 | for (String pkg : (String[]) attributes.get("value")) {
76 | if (StringUtils.hasText(pkg)) {
77 | basePackages.add(pkg);
78 | }
79 | }
80 | for (String pkg : (String[]) attributes.get("basePackages")) {
81 | if (StringUtils.hasText(pkg)) {
82 | basePackages.add(pkg);
83 | }
84 | }
85 | for (Class> clazz : (Class[]) attributes.get("basePackageClasses")) {
86 | basePackages.add(ClassUtils.getPackageName(clazz));
87 | }
88 |
89 | if (basePackages.isEmpty()) {
90 | basePackages.add(
91 | ClassUtils.getPackageName(importingClassMetadata.getClassName()));
92 | }
93 | return basePackages;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/retrofit-spring-boot-starter-demo/retrofit-spring-boot-starter-demo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------