Make spring-twitter-function as auto-config
* Fix Checkstyle violations in this module * Make all the Twitter function auto-configurations as conditional on their specific properties to avoid extra beans not expected in the target application * Fix README respectively
This commit is contained in:
@@ -2,34 +2,31 @@
|
||||
|
||||
This module provides couple of twitter functions that can be reused and composed in other applications.
|
||||
|
||||
To use those functions add the following dependency to your POM:
|
||||
This module exposes auto-configurations for the following beans:
|
||||
|
||||
[source,XML]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud.fn</groupId>
|
||||
<artifactId>twitter-function</artifactId>
|
||||
<version>${java-functions.version}</version>
|
||||
</dependency>
|
||||
----
|
||||
* `twitterTrendFunction`
|
||||
* `twitterUsersFunction`
|
||||
* `twitterGeoFunction`
|
||||
|
||||
Each of them are conditional by specific configuration properties.
|
||||
|
||||
## 1. Twitter Trend Function
|
||||
|
||||
Functions can return either Trends topics or the Locations of the trending topics. The `twitter.trend.trend-query-type` property allows choosing between both types.
|
||||
Function can return either Trends topics or the Locations of the trending topics.
|
||||
The `twitter.trend.trend-query-type` property allows choosing between both types.
|
||||
This property is required to enable the function auto-configuration.
|
||||
|
||||
* Trends - `twitter.trend.trend-query-type` is set to `trend`. Leverages the https://developer.twitter.com/en/docs/trends/trends-for-location/api-reference/get-trends-place[Trends API] to return the https://help.twitter.com/en/using-twitter/twitter-trending-faqs[trending topics] near a specific latitude, longitude location.
|
||||
* Trends - `twitter.trend.trend-query-type` is set to `trend`.
|
||||
Leverages the https://developer.twitter.com/en/docs/trends/trends-for-location/api-reference/get-trends-place[Trends API] to return the https://help.twitter.com/en/using-twitter/twitter-trending-faqs[trending topics] near a specific latitude, longitude location.
|
||||
|
||||
* Trend Locations - the `twitter.trend.trend-query-type` is set `trendLocation`. Retrieve a full or nearby locations list of trending topics by location. If the `latitude`, `longitude` parameters are NOT provided the processor performs the https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-available[Trends Available API] and returns the locations that Twitter has trending topic information for.
|
||||
* Trend Locations - the `twitter.trend.trend-query-type` is set `trendLocation`.
|
||||
Retrieve a full or nearby locations list of trending topics by location. If the `latitude`, `longitude` parameters are NOT provided the processor performs the https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-available[Trends Available API] and returns the locations that Twitter has trending topic information for.
|
||||
If the `latitude`, `longitude` parameters are provided the processor performs the https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-closest[Trends Closest API] and returns the locations that Twitter has trending topic information for, closest to a specified location.
|
||||
|
||||
Response is an array of `locations` that encode the location's WOEID and some other human-readable information such as a canonical name and country the location belongs in.
|
||||
|
||||
### 1.1 Beans for injection
|
||||
|
||||
You can import the `TwitterTrendFunctionConfiguration` in a Spring Boot application and then inject the following bean.
|
||||
|
||||
`filterFunction`
|
||||
|
||||
You can use `Function<Message<?>, Message<byte[]>> twitterTrendFunction` as a qualifier when injecting.
|
||||
|
||||
Once injected, you can use the `apply` method of the `Function` to invoke it and get the result.
|
||||
@@ -45,12 +42,11 @@ See this link:src/test/java/org/springframework/cloud/fn/twitter/trend/TwitterTr
|
||||
|
||||
### 1.4 Other usage
|
||||
|
||||
Leveraging the Spring Cloud Function composability, you can compose the Trend function in your boot app like this:
|
||||
Leveraging the Spring Cloud Function "composability", you can compose the Trend function in your boot app like this:
|
||||
|
||||
[source,Java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@Import(TwitterTrendFunctionConfiguration.class )
|
||||
public class MyTwitterTrendBootApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -79,12 +75,10 @@ Some parameters in this method are only required based on the existence of other
|
||||
|
||||
NOTE: Limits: 15 requests / 15-min window (user auth).
|
||||
|
||||
This function auto-configuration is conditional on `twitter.geo.search.ip != null || (twitter.geo.location.lat != null && twitter.geo.location.lon != null)`
|
||||
|
||||
### 2.1 Beans for injection
|
||||
|
||||
You can import the `TwitterGeoFunctionConfiguration` in a Spring Boot application and then inject the following bean.
|
||||
|
||||
`filterFunction`
|
||||
|
||||
You can use `Function<Message<?>, Message<byte[]>> twitterGeoFunction` as a qualifier when injecting.
|
||||
Once injected, you can use the `apply` method of the `Function` to invoke it and get the result.
|
||||
|
||||
@@ -96,7 +90,7 @@ For more information on the various options available, please see link:../twitte
|
||||
|
||||
### 2.3 Tests
|
||||
|
||||
See this link:src/test/java/org/springframework/cloud/fn/twitter/geo/TwitterGeoFunctionTest.java[test suite] for examples of how this function is used.
|
||||
See this link:src/test/java/org/springframework/cloud/fn/twitter/geo/TwitterGeoFunctionTests.java[test suite] for examples of how this function is used.
|
||||
|
||||
### 2.4 Other usage
|
||||
|
||||
@@ -105,7 +99,6 @@ Leveraging the Spring Cloud Function composability, you can compose the Geo func
|
||||
[source,Java]
|
||||
----
|
||||
@SpringBootApplication
|
||||
@Import(TwitterGeoFunctionConfiguration.class )
|
||||
public class MyTwitterGeoProcessorBootApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -122,6 +115,7 @@ Uses SpEL expressions to compute the query parameters from the input message.
|
||||
Use the single quoted literals to set static values (e.g. user-id: '6666, 9999, 10000').
|
||||
|
||||
Use `twitter.users.type` property allow to select the query approaches.
|
||||
This property is required to trigger the `twitterUsersFunction` auto-configuration.
|
||||
|
||||
* https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup[Users Lookup API] - Returns fully-hydrated user objects for up to 100 users per request, as specified by comma-separated values passed to the `userId` and/or `screenName` parameters. Rate limits: (300 requests / 15-min window)
|
||||
* https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search[Users Search API] - Relevance-based search interface to public user accounts on Twitter.
|
||||
@@ -129,10 +123,6 @@ Querying by topical interest, full name, company name, location, or other criter
|
||||
|
||||
### 3.1 Beans for injection
|
||||
|
||||
You can import the `TwitterUsersFunctionConfiguration` in a Spring Boot application and then inject the following bean.
|
||||
|
||||
`filterFunction`
|
||||
|
||||
You can use `Function<Message<?>, Message<byte[]>> twitterUsersFunction` as a qualifier when injecting.
|
||||
Once injected, you can use the `apply` method of the `Function` to invoke it and get the result.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,27 +27,29 @@ import twitter4j.Place;
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.fn.common.twitter.TwitterConnectionConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Twitter Geo function.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnExpression("environment['twitter.geo.search.ip'] != null || (environment['twitter.geo.location.lat'] != null && environment['twitter.geo.location.lon'] != null)")
|
||||
@AutoConfiguration(after = TwitterConnectionConfiguration.class)
|
||||
@EnableConfigurationProperties(TwitterGeoFunctionProperties.class)
|
||||
@Import(TwitterConnectionConfiguration.class)
|
||||
public class TwitterGeoFunctionConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TwitterGeoFunctionConfiguration.class);
|
||||
private static final Log LOGGER = LogFactory.getLog(TwitterGeoFunctionConfiguration.class);
|
||||
|
||||
@Bean
|
||||
public Function<Message<?>, GeoQuery> messageToGeoQueryFunction(TwitterGeoFunctionProperties geoProperties) {
|
||||
return message -> {
|
||||
return (message) -> {
|
||||
String ip = null;
|
||||
if (geoProperties.getSearch().getIp() != null) {
|
||||
ip = geoProperties.getSearch().getIp().getValue(message, String.class);
|
||||
@@ -76,12 +78,12 @@ public class TwitterGeoFunctionConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "twitter.geo.search.type", havingValue = "search", matchIfMissing = true)
|
||||
public Function<GeoQuery, List<Place>> twitterSearchPlacesFunction(Twitter twitter) {
|
||||
return geoQuery -> {
|
||||
return (geoQuery) -> {
|
||||
try {
|
||||
return twitter.searchPlaces(geoQuery);
|
||||
}
|
||||
catch (TwitterException e) {
|
||||
logger.error("Places Search failed!", e);
|
||||
catch (TwitterException ex) {
|
||||
LOGGER.error("Places Search failed!", ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -90,12 +92,12 @@ public class TwitterGeoFunctionConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "twitter.geo.search.type", havingValue = "reverse")
|
||||
public Function<GeoQuery, List<Place>> twitterReverseGeocodeFunction(Twitter twitter) {
|
||||
return geoQuery -> {
|
||||
return (geoQuery) -> {
|
||||
try {
|
||||
return twitter.reverseGeoCode(geoQuery);
|
||||
}
|
||||
catch (TwitterException e) {
|
||||
logger.error("Reverse Geocode failed!", e);
|
||||
catch (TwitterException ex) {
|
||||
LOGGER.error("Reverse Geocode failed!", ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -105,7 +107,7 @@ public class TwitterGeoFunctionConfiguration {
|
||||
public Function<Message<?>, Message<byte[]>> twitterGeoFunction(Function<Message<?>, GeoQuery> toGeoQuery,
|
||||
Function<GeoQuery, List<Place>> places, Function<Object, Message<byte[]>> managedJson) {
|
||||
|
||||
return toGeoQuery.andThen(places).andThen(managedJson)::apply;
|
||||
return toGeoQuery.andThen(places).andThen(managedJson);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,18 +21,17 @@ import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* Configuration properties for Twitter Geo function.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@ConfigurationProperties("twitter.geo")
|
||||
@Validated
|
||||
public class TwitterGeoFunctionProperties {
|
||||
|
||||
private static final Expression DEFAULT_EXPRESSION = new SpelExpressionParser().parseExpression("payload");
|
||||
|
||||
public enum GeoType {
|
||||
|
||||
/** Geo retrieval type. */
|
||||
@@ -51,9 +50,6 @@ public class TwitterGeoFunctionProperties {
|
||||
*/
|
||||
private Search search = new Search();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Location location = new Location();
|
||||
|
||||
/**
|
||||
@@ -68,7 +64,7 @@ public class TwitterGeoFunctionProperties {
|
||||
* in meters, but it can also take a string that is suffixed with ft to specify feet.
|
||||
* If this is not passed in, then it is assumed to be 0m. If coming from a device, in
|
||||
* practice, this value is whatever accuracy the device has measuring its location
|
||||
* (whether it be coming from a GPS, WiFi triangulation, etc.).
|
||||
* (whether it be coming from a GPS, Wi-Fi triangulation, etc.).
|
||||
*/
|
||||
private String accuracy = null;
|
||||
|
||||
@@ -79,7 +75,7 @@ public class TwitterGeoFunctionProperties {
|
||||
private String granularity = null;
|
||||
|
||||
public Search getSearch() {
|
||||
return search;
|
||||
return this.search;
|
||||
}
|
||||
|
||||
public void setSearch(Search search) {
|
||||
@@ -87,7 +83,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public GeoType getType() {
|
||||
return type;
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(GeoType type) {
|
||||
@@ -95,7 +91,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public void setLocation(Location location) {
|
||||
@@ -103,7 +99,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public int getMaxResults() {
|
||||
return maxResults;
|
||||
return this.maxResults;
|
||||
}
|
||||
|
||||
public void setMaxResults(int maxResults) {
|
||||
@@ -111,7 +107,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public String getAccuracy() {
|
||||
return accuracy;
|
||||
return this.accuracy;
|
||||
}
|
||||
|
||||
public void setAccuracy(String accuracy) {
|
||||
@@ -119,7 +115,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public String getGranularity() {
|
||||
return granularity;
|
||||
return this.granularity;
|
||||
}
|
||||
|
||||
public void setGranularity(String granularity) {
|
||||
@@ -128,13 +124,12 @@ public class TwitterGeoFunctionProperties {
|
||||
|
||||
@AssertTrue(message = "Either the IP or the Location must be set")
|
||||
public boolean isAtLeastOne() {
|
||||
return this.getSearch().getIp() == null
|
||||
^ (this.getLocation().getLat() == null && this.getLocation().getLon() == null);
|
||||
return getSearch().getIp() == null ^ (getLocation().getLat() == null && getLocation().getLon() == null);
|
||||
}
|
||||
|
||||
@AssertTrue(message = "The IP parameter is applicable only for 'Search' GeoType")
|
||||
public boolean isIpUsedWithSearchGeoType() {
|
||||
if (this.getSearch().getIp() != null) {
|
||||
if (getSearch().getIp() != null) {
|
||||
return this.type == GeoType.search;
|
||||
}
|
||||
return true;
|
||||
@@ -154,7 +149,7 @@ public class TwitterGeoFunctionProperties {
|
||||
private Expression query = null;
|
||||
|
||||
public Expression getIp() {
|
||||
return ip;
|
||||
return this.ip;
|
||||
}
|
||||
|
||||
public void setIp(Expression ip) {
|
||||
@@ -162,7 +157,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public Expression getQuery() {
|
||||
return query;
|
||||
return this.query;
|
||||
}
|
||||
|
||||
public void setQuery(Expression query) {
|
||||
@@ -184,7 +179,7 @@ public class TwitterGeoFunctionProperties {
|
||||
private Expression lon;
|
||||
|
||||
public Expression getLat() {
|
||||
return lat;
|
||||
return this.lat;
|
||||
}
|
||||
|
||||
public void setLat(Expression lat) {
|
||||
@@ -192,7 +187,7 @@ public class TwitterGeoFunctionProperties {
|
||||
}
|
||||
|
||||
public Expression getLon() {
|
||||
return lon;
|
||||
return this.lon;
|
||||
}
|
||||
|
||||
public void setLon(Expression lon) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The Twitter Geo function auto-configuration.
|
||||
*/
|
||||
package org.springframework.cloud.fn.twitter.geo;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,32 +27,34 @@ import twitter4j.Trends;
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.fn.common.twitter.TwitterConnectionConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Twitter Trend function.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "twitter.trend", name = "trend-query-type")
|
||||
@AutoConfiguration(after = TwitterConnectionConfiguration.class)
|
||||
@EnableConfigurationProperties(TwitterTrendFunctionProperties.class)
|
||||
@Import(TwitterConnectionConfiguration.class)
|
||||
public class TwitterTrendFunctionConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TwitterTrendFunctionConfiguration.class);
|
||||
private static final Log LOGGER = LogFactory.getLog(TwitterTrendFunctionConfiguration.class);
|
||||
|
||||
@Bean
|
||||
public Function<Message<?>, Trends> trend(TwitterTrendFunctionProperties properties, Twitter twitter) {
|
||||
return message -> {
|
||||
return (message) -> {
|
||||
try {
|
||||
int woeid = properties.getLocationId().getValue(message, int.class);
|
||||
return twitter.getPlaceTrends(woeid);
|
||||
}
|
||||
catch (TwitterException e) {
|
||||
logger.error("Twitter API error!", e);
|
||||
catch (TwitterException ex) {
|
||||
LOGGER.error("Twitter API error!", ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -61,7 +63,8 @@ public class TwitterTrendFunctionConfiguration {
|
||||
@Bean
|
||||
public Function<Message<?>, List<Location>> closestOrAvailableTrends(TwitterTrendFunctionProperties properties,
|
||||
Twitter twitter) {
|
||||
return message -> {
|
||||
|
||||
return (message) -> {
|
||||
try {
|
||||
if (properties.getClosest().getLat() != null && properties.getClosest().getLon() != null) {
|
||||
double lat = properties.getClosest().getLat().getValue(message, double.class);
|
||||
@@ -72,8 +75,8 @@ public class TwitterTrendFunctionConfiguration {
|
||||
return twitter.getAvailableTrends();
|
||||
}
|
||||
}
|
||||
catch (TwitterException e) {
|
||||
logger.error("Twitter API error!", e);
|
||||
catch (TwitterException ex) {
|
||||
LOGGER.error("Twitter API error!", ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,19 +20,22 @@ import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* Configuration properties for Twitter Trend function.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@ConfigurationProperties("twitter.trend")
|
||||
@Validated
|
||||
public class TwitterTrendFunctionProperties {
|
||||
|
||||
private static final Expression DEFAULT_EXPRESSION = new SpelExpressionParser().parseExpression("payload");
|
||||
private static final Expression DEFAULT_EXPRESSION = new FunctionExpression<Message<?>>(Message::getPayload);
|
||||
|
||||
enum TrendQueryType {
|
||||
public enum TrendQueryType {
|
||||
|
||||
/** Retrieve trending places. */
|
||||
trend,
|
||||
@@ -41,10 +44,10 @@ public class TwitterTrendFunctionProperties {
|
||||
|
||||
}
|
||||
|
||||
private TrendQueryType trendQueryType = TrendQueryType.trend;
|
||||
private TrendQueryType trendQueryType;
|
||||
|
||||
public TrendQueryType getTrendQueryType() {
|
||||
return trendQueryType;
|
||||
return this.trendQueryType;
|
||||
}
|
||||
|
||||
public void setTrendQueryType(TrendQueryType trendQueryType) {
|
||||
@@ -59,40 +62,39 @@ public class TwitterTrendFunctionProperties {
|
||||
private Expression locationId = DEFAULT_EXPRESSION;
|
||||
|
||||
public Expression getLocationId() {
|
||||
return locationId;
|
||||
return this.locationId;
|
||||
}
|
||||
|
||||
public void setLocationId(Expression locationId) {
|
||||
this.locationId = locationId;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Closest closest = new Closest();
|
||||
private final Closest closest = new Closest();
|
||||
|
||||
public Closest getClosest() {
|
||||
return closest;
|
||||
return this.closest;
|
||||
}
|
||||
|
||||
public static class Closest {
|
||||
|
||||
/**
|
||||
* If provided with a long parameter the available trend locations will be sorted
|
||||
* by distance, nearest to furthest, to the co-ordinate pair. The valid ranges for
|
||||
* longitude is -180.0 to +180.0 (West is negative, East is positive) inclusive.
|
||||
* by distance, nearest to the furthest, to the co-ordinate pair. The valid ranges
|
||||
* for longitude is -180.0 to +180.0 (West is negative, East is positive)
|
||||
* inclusive.
|
||||
*/
|
||||
private Expression lat;
|
||||
|
||||
/**
|
||||
* If provided with a lat parameter the available trend locations will be sorted
|
||||
* by distance, nearest to furthest, to the co-ordinate pair. The valid ranges for
|
||||
* longitude is -180.0 to +180.0 (West is negative, East is positive) inclusive.
|
||||
* by distance, nearest to the furthest, to the co-ordinate pair. The valid ranges
|
||||
* for longitude is -180.0 to +180.0 (West is negative, East is positive)
|
||||
* inclusive.
|
||||
*/
|
||||
private Expression lon;
|
||||
|
||||
public Expression getLat() {
|
||||
return lat;
|
||||
return this.lat;
|
||||
}
|
||||
|
||||
public void setLat(Expression lat) {
|
||||
@@ -100,7 +102,7 @@ public class TwitterTrendFunctionProperties {
|
||||
}
|
||||
|
||||
public Expression getLon() {
|
||||
return lon;
|
||||
return this.lon;
|
||||
}
|
||||
|
||||
public void setLon(Expression lon) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The Twitter Trend function auto-configuration.
|
||||
*/
|
||||
package org.springframework.cloud.fn.twitter.trend;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,41 +21,40 @@ import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import twitter4j.ResponseList;
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
import twitter4j.User;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.fn.common.twitter.TwitterConnectionConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* Auto-configuration for Twitter Users function.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "twitter.users", name = "type")
|
||||
@AutoConfiguration(after = TwitterConnectionConfiguration.class)
|
||||
@EnableConfigurationProperties(TwitterUsersFunctionProperties.class)
|
||||
@Import(TwitterConnectionConfiguration.class)
|
||||
public class TwitterUsersFunctionConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TwitterUsersFunctionConfiguration.class);
|
||||
private static final Log LOGGER = LogFactory.getLog(TwitterUsersFunctionConfiguration.class);
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "twitter.users.type", havingValue = "search")
|
||||
public Function<Message<?>, List<User>> userSearch(Twitter twitter, TwitterUsersFunctionProperties properties) {
|
||||
|
||||
return message -> {
|
||||
return (message) -> {
|
||||
String query = properties.getSearch().getQuery().getValue(message, String.class);
|
||||
try {
|
||||
ResponseList<User> users = twitter.searchUsers(query, properties.getSearch().getPage());
|
||||
return users;
|
||||
return twitter.searchUsers(query, properties.getSearch().getPage());
|
||||
}
|
||||
catch (TwitterException e) {
|
||||
logger.error("Twitter API error!", e);
|
||||
catch (TwitterException ex) {
|
||||
LOGGER.error("Twitter API error!", ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -65,7 +64,7 @@ public class TwitterUsersFunctionConfiguration {
|
||||
@ConditionalOnProperty(name = "twitter.users.type", havingValue = "lookup")
|
||||
public Function<Message<?>, List<User>> userLookup(Twitter twitter, TwitterUsersFunctionProperties properties) {
|
||||
|
||||
return message -> {
|
||||
return (message) -> {
|
||||
|
||||
try {
|
||||
TwitterUsersFunctionProperties.Lookup lookup = properties.getLookup();
|
||||
@@ -78,20 +77,17 @@ public class TwitterUsersFunctionConfiguration {
|
||||
return twitter.lookupUsers(ids);
|
||||
}
|
||||
}
|
||||
catch (TwitterException e) {
|
||||
logger.error("Twitter API error!", e);
|
||||
catch (TwitterException ex) {
|
||||
LOGGER.error("Twitter API error!", ex);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
/**
|
||||
* queryUsers - depends on the `twitter.users.type` property is either userSearch or
|
||||
* userLookup. managedJson - converts Users into JSON message payload.
|
||||
*/
|
||||
public Function<Message<?>, Message<byte[]>> twitterUsersFunction(Function<Message<?>, List<User>> queryUsers,
|
||||
Function<Object, Message<byte[]>> managedJson) {
|
||||
|
||||
return queryUsers.andThen(managedJson);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,21 +17,23 @@
|
||||
package org.springframework.cloud.fn.twitter.users;
|
||||
|
||||
import jakarta.validation.constraints.AssertTrue;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.expression.FunctionExpression;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* Configuration properties for Twitter Users function.
|
||||
*
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@ConfigurationProperties("twitter.users")
|
||||
@Validated
|
||||
public class TwitterUsersFunctionProperties {
|
||||
|
||||
private static final Expression DEFAULT_EXPRESSION = new SpelExpressionParser().parseExpression("payload");
|
||||
private static final Expression DEFAULT_EXPRESSION = new FunctionExpression<Message<?>>(Message::getPayload);
|
||||
|
||||
public enum UserQueryType {
|
||||
|
||||
@@ -43,8 +45,7 @@ public class TwitterUsersFunctionProperties {
|
||||
/**
|
||||
* Perform search or lookup type of search.
|
||||
*/
|
||||
@NotNull
|
||||
private UserQueryType type = UserQueryType.search;
|
||||
private UserQueryType type;
|
||||
|
||||
/**
|
||||
* Returns fully-hydrated user objects for specified by comma-separated values passed
|
||||
@@ -53,13 +54,13 @@ public class TwitterUsersFunctionProperties {
|
||||
private final Lookup lookup = new Lookup();
|
||||
|
||||
/**
|
||||
* relevance-based search interface for querying by topical interest, full name,
|
||||
* Relevance-based search interface for querying by topical interest, full name,
|
||||
* company name, location, or other criteria.
|
||||
*/
|
||||
private final Search search = new Search();
|
||||
|
||||
public UserQueryType getType() {
|
||||
return type;
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public void setType(UserQueryType type) {
|
||||
@@ -67,20 +68,20 @@ public class TwitterUsersFunctionProperties {
|
||||
}
|
||||
|
||||
public Lookup getLookup() {
|
||||
return lookup;
|
||||
return this.lookup;
|
||||
}
|
||||
|
||||
public Search getSearch() {
|
||||
return search;
|
||||
return this.search;
|
||||
}
|
||||
|
||||
@AssertTrue(message = "Per query type validate the required parameters")
|
||||
public boolean checkParametersPerType() {
|
||||
if (this.getType() == UserQueryType.lookup) {
|
||||
return (this.getLookup().getScreenName() != null) || (this.getLookup().getUserId() != null);
|
||||
if (getType() == UserQueryType.lookup) {
|
||||
return (getLookup().getScreenName() != null) || (getLookup().getUserId() != null);
|
||||
}
|
||||
else if (this.getType() == UserQueryType.search) {
|
||||
return (this.getSearch().getQuery() != null);
|
||||
else if (getType() == UserQueryType.search) {
|
||||
return (getSearch().getQuery() != null);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -102,7 +103,7 @@ public class TwitterUsersFunctionProperties {
|
||||
private Expression screenName;
|
||||
|
||||
public Expression getUserId() {
|
||||
return userId;
|
||||
return this.userId;
|
||||
}
|
||||
|
||||
public void setUserId(Expression userId) {
|
||||
@@ -110,7 +111,7 @@ public class TwitterUsersFunctionProperties {
|
||||
}
|
||||
|
||||
public Expression getScreenName() {
|
||||
return screenName;
|
||||
return this.screenName;
|
||||
}
|
||||
|
||||
public void setScreenName(Expression screenName) {
|
||||
@@ -132,7 +133,7 @@ public class TwitterUsersFunctionProperties {
|
||||
private int page = 3;
|
||||
|
||||
public Expression getQuery() {
|
||||
return query;
|
||||
return this.query;
|
||||
}
|
||||
|
||||
public void setQuery(Expression query) {
|
||||
@@ -140,7 +141,7 @@ public class TwitterUsersFunctionProperties {
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
return this.page;
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The Twitter Users function auto-configuration.
|
||||
*/
|
||||
package org.springframework.cloud.fn.twitter.users;
|
||||
@@ -0,0 +1,3 @@
|
||||
org.springframework.cloud.fn.twitter.geo.TwitterGeoFunctionConfiguration
|
||||
org.springframework.cloud.fn.twitter.trend.TwitterTrendFunctionConfiguration
|
||||
org.springframework.cloud.fn.twitter.users.TwitterUsersFunctionConfiguration
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,13 +40,11 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.fn.common.twitter.TwitterConnectionProperties;
|
||||
import org.springframework.cloud.fn.common.twitter.util.TwitterTestUtils;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.util.TestSocketUtils;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -58,17 +56,14 @@ import static org.mockserver.verify.VerificationTimes.once;
|
||||
/**
|
||||
* @author Christian Tzolov
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
properties = { "twitter.connection.consumerKey=consumerKey666",
|
||||
"twitter.connection.consumerSecret=consumerSecret666", "twitter.connection.accessToken=accessToken666",
|
||||
"twitter.connection.accessTokenSecret=accessTokenSecret666" })
|
||||
@SpringBootTest(properties = { "twitter.connection.consumerKey=consumerKey666",
|
||||
"twitter.connection.consumerSecret=consumerSecret666", "twitter.connection.accessToken=accessToken666",
|
||||
"twitter.connection.accessTokenSecret=accessTokenSecret666" })
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
public abstract class TwitterGeoFunctionTest {
|
||||
public abstract class TwitterGeoFunctionTests {
|
||||
|
||||
private static final String MOCK_SERVER_IP = "127.0.0.1";
|
||||
|
||||
private static final Integer MOCK_SERVER_PORT = TestSocketUtils.findAvailableTcpPort();
|
||||
|
||||
private static ClientAndServer mockServer;
|
||||
|
||||
private static MockServerClient mockClient;
|
||||
@@ -90,8 +85,8 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void startMockServer() {
|
||||
mockServer = ClientAndServer.startClientAndServer(MOCK_SERVER_PORT);
|
||||
mockClient = new MockServerClient(MOCK_SERVER_IP, MOCK_SERVER_PORT);
|
||||
mockServer = ClientAndServer.startClientAndServer();
|
||||
mockClient = new MockServerClient(MOCK_SERVER_IP, mockServer.getPort());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -101,7 +96,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
@TestPropertySource(
|
||||
properties = { "twitter.geo.search.ip='127.0.0.1'", "twitter.geo.search.query=payload.toUpperCase()" })
|
||||
public static class TwitterGeoSearchByIPAndQueryTests extends TwitterGeoFunctionTest {
|
||||
public static class TwitterGeoSearchByIPAndQueryTests extends TwitterGeoFunctionTests {
|
||||
|
||||
@Test
|
||||
public void testOne() throws IOException {
|
||||
@@ -125,7 +120,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
assertThat(outPayload).isNotNull();
|
||||
|
||||
List places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
List<?> places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
assertThat(places).hasSize(12);
|
||||
}
|
||||
|
||||
@@ -133,7 +128,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
@TestPropertySource(properties = { "twitter.geo.location.lat='52.378'", "twitter.geo.location.lon='4.9'",
|
||||
"twitter.geo.search.query=payload.toUpperCase()" })
|
||||
public static class TwitterGeoSearchByLocationTests extends TwitterGeoFunctionTest {
|
||||
public static class TwitterGeoSearchByLocationTests extends TwitterGeoFunctionTests {
|
||||
|
||||
@Test
|
||||
public void testOne() throws IOException {
|
||||
@@ -159,7 +154,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
assertThat(outPayload).isNotNull();
|
||||
|
||||
List places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
List<?> places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
assertThat(places).hasSize(12);
|
||||
}
|
||||
|
||||
@@ -167,7 +162,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
@TestPropertySource(properties = { "twitter.geo.type=reverse", "twitter.geo.location.lat='52.378'",
|
||||
"twitter.geo.location.lon='4.9'" })
|
||||
public static class TwitterGeoSearchByLocation2Tests extends TwitterGeoFunctionTest {
|
||||
public static class TwitterGeoSearchByLocation2Tests extends TwitterGeoFunctionTests {
|
||||
|
||||
@Test
|
||||
public void testOne() throws IOException {
|
||||
@@ -191,7 +186,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
assertThat(outPayload).isNotNull();
|
||||
|
||||
List places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
List<?> places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
assertThat(places).hasSize(12);
|
||||
}
|
||||
|
||||
@@ -200,7 +195,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
@TestPropertySource(properties = { "twitter.geo.location.lat=#jsonPath(new String(payload),'$.location.lat')",
|
||||
"twitter.geo.location.lon=#jsonPath(new String(payload),'$.location.lon')",
|
||||
"twitter.geo.search.query=#jsonPath(new String(payload),'$.country')" })
|
||||
public static class TwitterGeoSearchJsonPathTests extends TwitterGeoFunctionTest {
|
||||
public static class TwitterGeoSearchJsonPathTests extends TwitterGeoFunctionTests {
|
||||
|
||||
@Test
|
||||
public void testOne() throws IOException {
|
||||
@@ -228,7 +223,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
assertThat(outPayload).isNotNull();
|
||||
|
||||
List places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
List<?> places = new ObjectMapper().readValue(outPayload, List.class);
|
||||
assertThat(places).hasSize(12);
|
||||
}
|
||||
|
||||
@@ -236,7 +231,6 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@Import(TwitterGeoFunctionConfiguration.class)
|
||||
public static class TwitterGeoFunctionTestApplication {
|
||||
|
||||
@Bean
|
||||
@@ -246,7 +240,7 @@ public abstract class TwitterGeoFunctionTest {
|
||||
|
||||
Function<TwitterConnectionProperties, ConfigurationBuilder> mockedConfiguration = toConfigurationBuilder
|
||||
.andThen(new TwitterTestUtils()
|
||||
.mockTwitterUrls(String.format("http://%s:%s", MOCK_SERVER_IP, MOCK_SERVER_PORT)));
|
||||
.mockTwitterUrls(String.format("http://%s:%s", MOCK_SERVER_IP, mockServer.getPort())));
|
||||
|
||||
return mockedConfiguration.apply(properties).build();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,13 +35,11 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.fn.common.twitter.TwitterConnectionProperties;
|
||||
import org.springframework.cloud.fn.common.twitter.util.TwitterTestUtils;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.util.TestSocketUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockserver.matchers.Times.exactly;
|
||||
@@ -61,8 +59,6 @@ public abstract class TwitterTrendFunctionTests {
|
||||
|
||||
private static final String MOCK_SERVER_IP = "127.0.0.1";
|
||||
|
||||
private static final Integer MOCK_SERVER_PORT = TestSocketUtils.findAvailableTcpPort();
|
||||
|
||||
private static ClientAndServer mockServer;
|
||||
|
||||
private static MockServerClient mockClient;
|
||||
@@ -74,8 +70,8 @@ public abstract class TwitterTrendFunctionTests {
|
||||
|
||||
@BeforeAll
|
||||
public static void startServer() {
|
||||
mockServer = ClientAndServer.startClientAndServer(MOCK_SERVER_PORT);
|
||||
mockClient = new MockServerClient(MOCK_SERVER_IP, MOCK_SERVER_PORT);
|
||||
mockServer = ClientAndServer.startClientAndServer();
|
||||
mockClient = new MockServerClient(MOCK_SERVER_IP, mockServer.getPort());
|
||||
|
||||
trendsRequest = setExpectation(
|
||||
request().withMethod("GET").withPath("/trends/place.json").withQueryStringParameter("id", "2972"));
|
||||
@@ -96,7 +92,8 @@ public abstract class TwitterTrendFunctionTests {
|
||||
return request;
|
||||
}
|
||||
|
||||
@TestPropertySource(properties = { "twitter.trend.locationId='2972'", "twitter.connection.rawJson=true" })
|
||||
@TestPropertySource(properties = { "twitter.trend.trendQueryType=trend", "twitter.trend.locationId='2972'",
|
||||
"twitter.connection.rawJson=true" })
|
||||
public static class TwitterTrendPayloadTests extends TwitterTrendFunctionTests {
|
||||
|
||||
@Test
|
||||
@@ -110,7 +107,6 @@ public abstract class TwitterTrendFunctionTests {
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@Import(TwitterTrendFunctionConfiguration.class)
|
||||
public static class TwitterTrendFunctionTestApplication {
|
||||
|
||||
@Bean
|
||||
@@ -120,7 +116,7 @@ public abstract class TwitterTrendFunctionTests {
|
||||
|
||||
Function<TwitterConnectionProperties, ConfigurationBuilder> mockedConfiguration = toConfigurationBuilder
|
||||
.andThen(new TwitterTestUtils()
|
||||
.mockTwitterUrls(String.format("http://%s:%s", MOCK_SERVER_IP, MOCK_SERVER_PORT)));
|
||||
.mockTwitterUrls(String.format("http://%s:%s", MOCK_SERVER_IP, mockServer.getPort())));
|
||||
|
||||
return mockedConfiguration.apply(properties).build();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2020-2020 the original author or authors.
|
||||
* Copyright 2020-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,13 +38,11 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.fn.common.twitter.TwitterConnectionProperties;
|
||||
import org.springframework.cloud.fn.common.twitter.util.TwitterTestUtils;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.util.TestSocketUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockserver.matchers.Times.exactly;
|
||||
@@ -64,8 +62,6 @@ public abstract class TwitterUsersFunctionTests {
|
||||
|
||||
private static final String MOCK_SERVER_IP = "127.0.0.1";
|
||||
|
||||
private static final Integer MOCK_SERVER_PORT = TestSocketUtils.findAvailableTcpPort();
|
||||
|
||||
private static ClientAndServer mockServer;
|
||||
|
||||
private static MockServerClient mockClient;
|
||||
@@ -94,8 +90,8 @@ public abstract class TwitterUsersFunctionTests {
|
||||
|
||||
@BeforeAll
|
||||
public static void startServer() {
|
||||
mockServer = ClientAndServer.startClientAndServer(MOCK_SERVER_PORT);
|
||||
mockClient = new MockServerClient(MOCK_SERVER_IP, MOCK_SERVER_PORT);
|
||||
mockServer = ClientAndServer.startClientAndServer();
|
||||
mockClient = new MockServerClient(MOCK_SERVER_IP, mockServer.getPort());
|
||||
|
||||
searchUsersRequest = setExpectation(request().withMethod("GET")
|
||||
.withPath("/users/search.json")
|
||||
@@ -127,7 +123,7 @@ public abstract class TwitterUsersFunctionTests {
|
||||
Message<?> received = twitterUsersFunction.apply(MessageBuilder.withPayload("tzolov").build());
|
||||
mockClient.verify(searchUsersRequest, once());
|
||||
assertThat(received).isNotNull();
|
||||
List list = mapper.readValue(new String((byte[]) received.getPayload()), List.class);
|
||||
List<?> list = mapper.readValue(new String((byte[]) received.getPayload()), List.class);
|
||||
assertThat(list).hasSize(20);
|
||||
}
|
||||
|
||||
@@ -144,7 +140,7 @@ public abstract class TwitterUsersFunctionTests {
|
||||
|
||||
mockClient.verify(lookupUsersRequest, once());
|
||||
assertThat(received).isNotNull();
|
||||
List list = mapper.readValue(new String((byte[]) received.getPayload()), List.class);
|
||||
List<?> list = mapper.readValue(new String((byte[]) received.getPayload()), List.class);
|
||||
assertThat(list).hasSize(5);
|
||||
}
|
||||
|
||||
@@ -164,7 +160,7 @@ public abstract class TwitterUsersFunctionTests {
|
||||
|
||||
mockClient.verify(lookupUsersRequest2, once());
|
||||
assertThat(received).isNotNull();
|
||||
List list = mapper.readValue(new String((byte[]) received.getPayload()), List.class);
|
||||
List<?> list = mapper.readValue(new String((byte[]) received.getPayload()), List.class);
|
||||
assertThat(list).hasSize(5);
|
||||
}
|
||||
|
||||
@@ -172,17 +168,16 @@ public abstract class TwitterUsersFunctionTests {
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration
|
||||
@Import(TwitterUsersFunctionConfiguration.class)
|
||||
static class TwitterUsersFunctionTestApplication {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public twitter4j.conf.Configuration twitterConfiguration2(TwitterConnectionProperties properties,
|
||||
twitter4j.conf.Configuration twitterConfiguration2(TwitterConnectionProperties properties,
|
||||
Function<TwitterConnectionProperties, ConfigurationBuilder> toConfigurationBuilder) {
|
||||
|
||||
Function<TwitterConnectionProperties, ConfigurationBuilder> mockedConfiguration = toConfigurationBuilder
|
||||
.andThen(new TwitterTestUtils()
|
||||
.mockTwitterUrls(String.format("http://%s:%s", MOCK_SERVER_IP, MOCK_SERVER_PORT)));
|
||||
.mockTwitterUrls(String.format("http://%s:%s", MOCK_SERVER_IP, mockServer.getPort())));
|
||||
|
||||
return mockedConfiguration.apply(properties).build();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user