Skip to content

Commit 553347b

Browse files
budaidevadamsaghy
authored andcommitted
FINERACT-2380: create feign client
1 parent f193bbb commit 553347b

File tree

56 files changed

+7908
-23
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+7908
-23
lines changed

build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ buildscript {
4444
'twofactor-tests',
4545
'oauth2-tests',
4646
'fineract-client',
47+
'fineract-client-feign',
4748
'fineract-avro-schemas',
4849
'fineract-e2e-tests-core',
4950
'fineract-e2e-tests-runner',
@@ -55,6 +56,7 @@ buildscript {
5556
[
5657
'fineract-avro-schemas',
5758
'fineract-client',
59+
'fineract-client-feign',
5860
'fineract-core',
5961
'fineract-cob',
6062
'fineract-validation',
@@ -558,6 +560,9 @@ configure(project.fineractJavaProjects) {
558560
if (project.path == ':fineract-client') {
559561
excludedPaths = '.*/build/generated/java/src/main/java/.*'
560562
}
563+
if (project.path == ':fineract-client-feign') {
564+
excludedPaths = '.*/build/generated/java/src/main/java/.*'
565+
}
561566
disable(
562567
// TODO Remove disabled checks from this list, by fixing remaining usages
563568
"UnusedVariable",
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
**/README.md
2+
**/pom.xml
3+
**/build.sbt
4+
**/*.gradle
5+
**/.gitignore
6+
**/git_push.sh
7+
**/api/*
8+
**/gradle*
9+
**/gradle
10+
**/src/main/AndroidManifest.xml
11+
12+
# https://issues.apache.org/jira/browse/FINERACT-1231
13+
**/feign/*.java
14+
!**/feign/CollectionFormats.java
15+
!**/feign/StringUtil.java
16+
17+
# Manual API overrides - do not regenerate
18+
# https://issues.apache.org/jira/browse/FINERACT-1263
19+
**/services/RunReportsApi.java
20+
**/services/ImagesApi.java
21+
**/services/DocumentsApiFixed.java
22+
23+
# Utility classes - do not regenerate
24+
**/util/*.java
25+
**/adapter/*.java
26+
27+
# Feign configuration - do not regenerate
28+
**/feign/FineractFeignClient.java
29+
**/feign/FineractFeignClientConfig.java
30+
**/feign/BasicAuthRequestInterceptor.java
31+
**/feign/ObjectMapperFactory.java
32+
**/feign/FeignException.java

fineract-client-feign/build.gradle

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
apply plugin: 'org.openapi.generator'
20+
apply plugin: 'jacoco'
21+
description = 'Fineract Client with Feign'
22+
23+
apply from: 'dependencies.gradle'
24+
25+
openApiMeta {
26+
generatorName = 'Fineract-Feign'
27+
packageName = 'org.apache.fineract.client.feign'
28+
outputFolder = "$buildDir/meta".toString()
29+
}
30+
31+
openApiValidate {
32+
inputSpec = "file:///$swaggerFile"
33+
recommend = true
34+
}
35+
36+
tasks.register('buildJavaSdk', org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
37+
generatorName = 'java'
38+
library = 'feign'
39+
verbose = false
40+
validateSpec = false
41+
skipValidateSpec = true
42+
inputSpec = "file:///$swaggerFile"
43+
outputDir = "$buildDir/generated/temp-java".toString()
44+
templateDir = "$projectDir/src/main/resources/templates/java"
45+
groupId = 'org.apache.fineract'
46+
apiPackage = 'org.apache.fineract.client.feign.services'
47+
invokerPackage = 'org.apache.fineract.client.feign'
48+
modelPackage = 'org.apache.fineract.client.models'
49+
generateModelTests = false
50+
generateApiTests = false
51+
ignoreFileOverride = "$projectDir/.openapi-generator-ignore"
52+
configOptions = [
53+
dateLibrary : 'java8',
54+
library : 'feign',
55+
feignVersion : '13.6',
56+
feignApacheHttpClient : 'true',
57+
useFeign13 : 'true',
58+
useFeignApacheHttpClient : 'true',
59+
hideGenerationTimestamp : 'true',
60+
containerDefaultToNull : 'true',
61+
oauth2Implementation : 'none',
62+
useJakartaEe : 'true'
63+
64+
]
65+
dependsOn(':fineract-provider:resolve')
66+
}
67+
68+
sourceSets {
69+
main {
70+
java {
71+
srcDirs = [
72+
new File(buildDir, "generated/java/src/main/java"),
73+
"$projectDir/src/main/java"
74+
]
75+
destinationDirectory = layout.buildDirectory.dir('classes/java/main').get().asFile
76+
}
77+
output.resourcesDir = layout.buildDirectory.dir('resources/main').get().asFile
78+
}
79+
test {
80+
java {
81+
destinationDirectory = layout.buildDirectory.dir('classes/java/test').get().asFile
82+
}
83+
output.resourcesDir = layout.buildDirectory.dir('resources/test').get().asFile
84+
}
85+
}
86+
87+
tasks.withType(Jar).configureEach {
88+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
89+
}
90+
91+
task cleanupGeneratedJavaFiles() {
92+
def tempDir = file("$buildDir/generated/temp-java")
93+
def targetDir = file("$buildDir/generated/java")
94+
95+
inputs.dir(tempDir)
96+
outputs.dir(targetDir)
97+
98+
doLast {
99+
copy {
100+
from tempDir
101+
into targetDir
102+
filter { line ->
103+
line
104+
.replaceAll(", \\)", ")")
105+
.replaceAll(", , @HeaderMap", ", @HeaderMap")
106+
.replaceAll("\\(, ", "(")
107+
}
108+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
109+
}
110+
}
111+
dependsOn("buildJavaSdk")
112+
}
113+
114+
tasks.named('compileJava') {
115+
outputs.cacheIf { true }
116+
dependsOn(buildJavaSdk, cleanupGeneratedJavaFiles, licenseFormatMain, spotlessMiscApply)
117+
mustRunAfter(licenseFormatMain, cleanupGeneratedJavaFiles)
118+
}
119+
120+
tasks.named('sourcesJar') {
121+
dependsOn(cleanupGeneratedJavaFiles)
122+
mustRunAfter(cleanupGeneratedJavaFiles)
123+
124+
from(sourceSets.main.java.srcDirs) {
125+
include "**/*.java"
126+
}
127+
}
128+
129+
tasks.named('licenseFormatMain') {
130+
dependsOn(cleanupGeneratedJavaFiles)
131+
mustRunAfter(cleanupGeneratedJavaFiles)
132+
source = sourceSets.main.java.srcDirs
133+
}
134+
135+
tasks.named('licenseMain') {
136+
dependsOn(licenseFormatMain)
137+
mustRunAfter(licenseFormatMain)
138+
}
139+
140+
tasks.withType(JavaCompile).configureEach {
141+
options.encoding = 'UTF-8'
142+
options.compilerArgs << '-parameters'
143+
options.errorprone {
144+
excludedPaths = '.*/build/generated/java/src/main/java/.*'
145+
}
146+
}
147+
148+
test {
149+
useJUnitPlatform()
150+
}
151+
152+
configurations {
153+
generatedCompileClasspath.extendsFrom implementation
154+
generatedRuntimeClasspath.extendsFrom runtimeClasspath
155+
}
156+
157+
javadoc {
158+
options.encoding = 'UTF-8'
159+
}
160+
161+
spotbugsMain {
162+
enabled = false
163+
}
164+
165+
spotbugsTest {
166+
enabled = false
167+
}
168+
169+
jacoco {
170+
toolVersion = "0.8.11"
171+
}
172+
173+
jacocoTestReport {
174+
dependsOn test
175+
reports {
176+
xml.required = true
177+
html.required = true
178+
csv.required = false
179+
}
180+
afterEvaluate {
181+
classDirectories.setFrom(files(classDirectories.files.collect {
182+
fileTree(dir: it, exclude: [
183+
'**/build/generated/**',
184+
'**/org/apache/fineract/client/models/**',
185+
'**/org/apache/fineract/client/services/**Api.class',
186+
'**/org/apache/fineract/client/auth/**'
187+
])
188+
}))
189+
}
190+
}
191+
192+
test {
193+
finalizedBy jacocoTestReport
194+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
dependencies {
20+
// Feign dependencies
21+
implementation(
22+
'io.github.openfeign:feign-core:13.6',
23+
'io.github.openfeign:feign-jackson:13.6',
24+
'io.github.openfeign:feign-slf4j:13.6',
25+
'io.github.openfeign:feign-hc5:13.6',
26+
'io.github.openfeign:feign-okhttp:13.6',
27+
'io.github.openfeign.form:feign-form:3.8.0',
28+
'org.apache.httpcomponents.client5:httpclient5:5.2.1',
29+
'com.squareup.okhttp3:okhttp:4.12.0',
30+
'com.fasterxml.jackson.core:jackson-databind',
31+
'com.fasterxml.jackson.datatype:jackson-datatype-jsr310',
32+
'com.fasterxml.jackson.datatype:jackson-datatype-jdk8',
33+
'jakarta.annotation:jakarta.annotation-api:3.0.0',
34+
'io.swagger.core.v3:swagger-annotations-jakarta:2.2.15',
35+
'org.apache.commons:commons-lang3:3.12.0',
36+
'org.slf4j:slf4j-api:1.7.36',
37+
'org.projectlombok:lombok'
38+
)
39+
40+
// Test dependencies
41+
testImplementation(
42+
'org.junit.jupiter:junit-jupiter-api:5.11.3',
43+
'org.junit.jupiter:junit-jupiter-engine:5.11.3',
44+
'org.mockito:mockito-core:5.14.2',
45+
'org.assertj:assertj-core:3.26.3',
46+
'org.slf4j:slf4j-simple:1.7.36',
47+
'org.wiremock:wiremock-standalone'
48+
)
49+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.client.adapter;
20+
21+
import com.fasterxml.jackson.core.JsonGenerator;
22+
import com.fasterxml.jackson.core.JsonParser;
23+
import com.fasterxml.jackson.databind.DeserializationContext;
24+
import com.fasterxml.jackson.databind.JsonDeserializer;
25+
import com.fasterxml.jackson.databind.JsonSerializer;
26+
import com.fasterxml.jackson.databind.SerializerProvider;
27+
import com.fasterxml.jackson.databind.module.SimpleModule;
28+
import java.io.IOException;
29+
import org.apache.fineract.client.models.ExternalId;
30+
31+
/**
32+
* Custom Jackson adapter for ExternalId type serialization and deserialization. This adapter ensures that ExternalId
33+
* objects are properly serialized to their string value and deserialized from string values.
34+
*/
35+
public final class ExternalIdAdapter {
36+
37+
private ExternalIdAdapter() {}
38+
39+
/**
40+
* Jackson Serializer for ExternalId. Serializes an ExternalId object to its string value, or null if the ExternalId
41+
* or its value is null.
42+
*/
43+
public static class Serializer extends JsonSerializer<ExternalId> {
44+
45+
@Override
46+
public void serialize(ExternalId value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
47+
if (value == null || value.getValue() == null) {
48+
gen.writeNull();
49+
} else {
50+
gen.writeString(value.getValue());
51+
}
52+
}
53+
}
54+
55+
/**
56+
* Jackson Deserializer for ExternalId. Deserializes a string value to an ExternalId object, or null if the input is
57+
* null.
58+
*/
59+
public static class Deserializer extends JsonDeserializer<ExternalId> {
60+
61+
@Override
62+
public ExternalId deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
63+
String value = p.getValueAsString();
64+
if (value == null) {
65+
return null;
66+
}
67+
ExternalId externalId = new ExternalId();
68+
externalId.setValue(value);
69+
return externalId;
70+
}
71+
}
72+
73+
/**
74+
* Creates a Jackson SimpleModule configured with the ExternalId serializer and deserializer.
75+
*
76+
* @return A configured SimpleModule ready to be registered with an ObjectMapper
77+
*/
78+
public static SimpleModule createModule() {
79+
SimpleModule module = new SimpleModule("ExternalIdModule");
80+
module.addSerializer(ExternalId.class, new Serializer());
81+
module.addDeserializer(ExternalId.class, new Deserializer());
82+
return module;
83+
}
84+
}

0 commit comments

Comments
 (0)