Browse Source

Create example that uses springboot (#1782)

pull/1788/head
Marvin Froeder 2 years ago committed by GitHub
parent
commit
58d49da0eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      example-wikipedia-with-springboot/README.md
  2. 118
      example-wikipedia-with-springboot/pom.xml
  3. 97
      example-wikipedia-with-springboot/src/main/java/example/wikipedia/ResponseAdapter.java
  4. 83
      example-wikipedia-with-springboot/src/main/java/example/wikipedia/WikipediaApplication.java
  5. 55
      example-wikipedia-with-springboot/src/main/java/example/wikipedia/WikipediaClient.java
  6. 63
      example-wikipedia-with-springboot/src/main/java/example/wikipedia/WikipediaClientConfiguration.java
  7. 45
      example-wikipedia-with-springboot/src/test/java/feign/example/wikipedia/WikipediaExampleIT.java
  8. 1
      pom.xml

4
example-wikipedia-with-springboot/README.md

@ -0,0 +1,4 @@
Wikipedia Example with Springboot
=================================
This is an example of advanced json response parsing, including pagination.

118
example-wikipedia-with-springboot/pom.xml

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2012-2022 The Feign Authors
Licensed 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
http://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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.github.openfeign</groupId>
<artifactId>parent</artifactId>
<version>12.0-SNAPSHOT</version>
</parent>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-example-wikipedia-with-springboot</artifactId>
<packaging>jar</packaging>
<name>Wikipedia Example</name>
<properties>
<main.basedir>${project.basedir}/..</main.basedir>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>example.wikipedia.WikipediaApplication</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.skife.maven</groupId>
<artifactId>really-executable-jar-maven-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<programFile>wikipedia</programFile>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>really-executable-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

97
example-wikipedia-with-springboot/src/main/java/example/wikipedia/ResponseAdapter.java

@ -0,0 +1,97 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed 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
*
* http://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 example.wikipedia;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
abstract class ResponseAdapter<X> extends TypeAdapter<WikipediaClient.Response<X>> {
/**
* name of the key inside the {@code query} dict which holds the elements desired. ex. {@code
* pages}.
*/
protected abstract String query();
/**
* Parses the contents of a result object.
* <p/>
* <br>
* ex. If {@link #query()} is {@code pages}, then this would parse the value of each key in the
* dict {@code pages}. In the example below, this would first start at line {@code 3}.
* <p/>
*
* <pre>
* "pages": {
* "2576129": {
* "pageid": 2576129,
* "title": "Burchell's zebra",
* --snip--
* </pre>
*/
protected abstract X build(JsonReader reader) throws IOException;
/**
* the wikipedia api doesn't use json arrays, rather a series of nested objects.
*/
@Override
public WikipediaClient.Response<X> read(JsonReader reader) throws IOException {
WikipediaClient.Response<X> pages = new WikipediaClient.Response<X>();
reader.beginObject();
while (reader.hasNext()) {
String nextName = reader.nextName();
if ("query".equals(nextName)) {
reader.beginObject();
while (reader.hasNext()) {
if (query().equals(reader.nextName())) {
reader.beginObject();
while (reader.hasNext()) {
// each element is in form: "id" : { object }
// this advances the pointer to the value and skips the key
reader.nextName();
reader.beginObject();
pages.add(build(reader));
reader.endObject();
}
reader.endObject();
} else {
reader.skipValue();
}
}
reader.endObject();
} else if ("continue".equals(nextName)) {
reader.beginObject();
while (reader.hasNext()) {
if ("gsroffset".equals(reader.nextName())) {
pages.nextOffset = reader.nextLong();
} else {
reader.skipValue();
}
}
reader.endObject();
} else {
reader.skipValue();
}
}
reader.endObject();
return pages;
}
@Override
public void write(JsonWriter out, WikipediaClient.Response<X> response) throws IOException {
throw new UnsupportedOperationException();
}
}

83
example-wikipedia-with-springboot/src/main/java/example/wikipedia/WikipediaApplication.java

@ -0,0 +1,83 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed 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
*
* http://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 example.wikipedia;
import example.wikipedia.WikipediaClient.Page;
import example.wikipedia.WikipediaClient.Response;
import example.wikipedia.WikipediaClient.Wikipedia;
import java.util.Iterator;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class WikipediaApplication {
public static void main(String[] args) {
SpringApplication.run(WikipediaApplication.class, args).start();;
}
@Autowired
private Wikipedia wikipedia;
@PostConstruct
public void run() {
System.out.println("Let's search for PTAL!");
Iterator<Page> pages = lazySearch(wikipedia, "PTAL");
while (pages.hasNext()) {
System.out.println(pages.next().title);
}
}
/**
* this will lazily continue searches, making new http calls as necessary.
*
* @param wikipedia used to search
* @param query see {@link Wikipedia#search(String)}.
*/
static Iterator<Page> lazySearch(final Wikipedia wikipedia, final String query) {
final Response<Page> first = wikipedia.search(query);
if (first.nextOffset == null) {
return first.iterator();
}
return new Iterator<Page>() {
Iterator<Page> current = first.iterator();
Long nextOffset = first.nextOffset;
@Override
public boolean hasNext() {
while (!current.hasNext() && nextOffset != null) {
System.out.println("Wow.. even more results than " + nextOffset);
Response<Page> nextPage = wikipedia.resumeSearch(query, nextOffset);
current = nextPage.iterator();
nextOffset = nextPage.nextOffset;
}
return current.hasNext();
}
@Override
public Page next() {
return current.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}

55
example-wikipedia-with-springboot/src/main/java/example/wikipedia/WikipediaClient.java

@ -0,0 +1,55 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed 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
*
* http://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 example.wikipedia;
import java.util.ArrayList;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
public class WikipediaClient {
@FeignClient(value = "jplaceholder", url = "https://en.wikipedia.org/",
configuration = WikipediaClientConfiguration.class)
public static interface Wikipedia {
@RequestMapping(method = RequestMethod.GET,
value = "/w/api.php?action=query&continue=&generator=search&prop=info&format=json&gsrsearch={search}")
Response<Page> search(@PathVariable("search") String search);
@RequestMapping(method = RequestMethod.GET,
value = "/w/api.php?action=query&continue=&generator=search&prop=info&format=json&gsrsearch={search}&gsroffset={offset}")
Response<Page> resumeSearch(@PathVariable("search") String search,
@PathVariable("offset") long offset);
}
static class Page {
long id;
String title;
}
public static class Response<X> extends ArrayList<X> {
/**
* when present, the position to resume the list.
*/
Long nextOffset;
}
}

63
example-wikipedia-with-springboot/src/main/java/example/wikipedia/WikipediaClientConfiguration.java

@ -0,0 +1,63 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed 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
*
* http://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 example.wikipedia;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import example.wikipedia.WikipediaClient.Page;
import example.wikipedia.WikipediaClient.Response;
import feign.codec.Decoder;
import feign.gson.GsonDecoder;
import java.io.IOException;
import org.springframework.context.annotation.Bean;
public class WikipediaClientConfiguration {
static ResponseAdapter<Page> pagesAdapter = new ResponseAdapter<Page>() {
@Override
protected String query() {
return "pages";
}
@Override
protected Page build(JsonReader reader) throws IOException {
Page page = new Page();
while (reader.hasNext()) {
String key = reader.nextName();
if (key.equals("pageid")) {
page.id = reader.nextLong();
} else if (key.equals("title")) {
page.title = reader.nextString();
} else {
reader.skipValue();
}
}
return page;
}
};
@Bean
public Decoder decoder() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<Response<Page>>() {}.getType(), pagesAdapter)
.create();
return new GsonDecoder(gson);
}
}

45
example-wikipedia-with-springboot/src/test/java/feign/example/wikipedia/WikipediaExampleIT.java

@ -0,0 +1,45 @@
/*
* Copyright 2012-2022 The Feign Authors
*
* Licensed 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
*
* http://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 feign.example.wikipedia;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.File;
import java.util.Arrays;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
/**
* Run main for {@link WikipediaExampleIT}
*/
public class WikipediaExampleIT {
@Test
public void runMain() throws Exception {
final String jar = Arrays.stream(new File("target").listFiles())
.filter(file -> file.getName().startsWith("feign-example-wikipedia-with-springboot")
&& file.getName().endsWith(".jar"))
.findFirst()
.map(File::getAbsolutePath)
.get();
final String line = "java -jar " + jar;
final CommandLine cmdLine = CommandLine.parse(line);
final int exitValue = new DefaultExecutor().execute(cmdLine);
assertThat(exitValue, CoreMatchers.equalTo(0));
}
}

1
pom.xml

@ -53,6 +53,7 @@
<module>example-github</module> <module>example-github</module>
<module>example-github-with-coroutine</module> <module>example-github-with-coroutine</module>
<module>example-wikipedia</module> <module>example-wikipedia</module>
<module>example-wikipedia-with-springboot</module>
<module>mock</module> <module>mock</module>
<module>apt-test-generator</module> <module>apt-test-generator</module>
<module>benchmark</module> <module>benchmark</module>

Loading…
Cancel
Save