Skip to content

Commit

Permalink
Improve debugging, add a test for OffersController.current()
Browse files Browse the repository at this point in the history
  • Loading branch information
graemerocher committed Feb 23, 2018
1 parent c20587c commit 66d7acc
Show file tree
Hide file tree
Showing 24 changed files with 216 additions and 76 deletions.
3 changes: 1 addition & 2 deletions examples/petclinic/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Thu Feb 22 09:40:35 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import example.api.v1.Offer;
import example.offers.client.v1.PetClient;
import io.lettuce.core.api.StatefulRedisConnection;
import org.particleframework.context.event.ApplicationEventListener;
import org.particleframework.runtime.ParticleApplication;
import org.particleframework.runtime.server.event.ServerStartupEvent;
Expand All @@ -39,10 +40,12 @@ public class Application implements ApplicationEventListener<ServerStartupEvent>

private final PetClient petClient;
private final OffersRepository offersRepository;
private final StatefulRedisConnection<String, String> redisConnection;

public Application(PetClient petClient, OffersRepository offersRepository) {
public Application(PetClient petClient, OffersRepository offersRepository, StatefulRedisConnection<String, String> redisConnection) {
this.petClient = petClient;
this.offersRepository = offersRepository;
this.redisConnection = redisConnection;
}

public static void main(String... args) {
Expand All @@ -51,7 +54,12 @@ public static void main(String... args) {

@Override
public void onApplicationEvent(ServerStartupEvent event) {
petClient.find("harry")
try {
redisConnection.sync().flushall();
} catch (Exception e) {
LOG.error("Error flushing Redis data: " +e.getMessage(), e);
}
petClient.find("harry")
.doOnError(throwable -> {
if (LOG.isErrorEnabled()) {
LOG.error("No pet found: " + throwable.getMessage(), throwable);
Expand Down Expand Up @@ -95,6 +103,26 @@ public void onApplicationEvent(ServerStartupEvent event) {
}
);


petClient.find("Goyle")
.doOnError(throwable -> {
if (LOG.isErrorEnabled()) {
LOG.error("No pet found: " + throwable.getMessage(), throwable);
}
})
.onErrorComplete()
.subscribe(pet -> {
Mono<Offer> savedOffer = offersRepository.save(
pet.getSlug(),
new BigDecimal("39.99"),
Duration.of(1, ChronoUnit.DAYS),
"Carefree Cat! Low Maintenance! Looking for a Home!");
savedOffer.subscribe((offer) -> {
}, throwable -> {
if (LOG.isErrorEnabled()) {
LOG.error("Error occurred saving offer: " + throwable.getMessage(), throwable);
}
});
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package example.offers;

import example.api.v1.Offer;
import org.particleframework.context.annotation.Value;
import org.particleframework.http.MediaType;
import org.particleframework.http.annotation.Controller;
import org.particleframework.http.annotation.Get;
Expand All @@ -41,9 +42,12 @@
public class OffersController implements OffersOperations {

private final OffersRepository offersRepository;
private final Duration offerDelay;

public OffersController(OffersRepository offersRepository) {

public OffersController(OffersRepository offersRepository, @Value("${offers.delay:5s}") Duration offerDelay) {
this.offersRepository = offersRepository;
this.offerDelay = offerDelay;
}

/**
Expand All @@ -55,7 +59,7 @@ public Flux<Offer> current() {
return offersRepository
.random()
.repeat()
.delayElements(Duration.ofSeconds(5));
.delayElements(offerDelay);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
package example.offers;

import example.api.v1.Offer;
import example.api.v1.Pet;
import example.offers.client.v1.PetClient;
import io.lettuce.core.KeyValue;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.reactive.RedisReactiveCommands;
import io.reactivex.Flowable;
import org.particleframework.core.convert.value.ConvertibleValues;
import org.particleframework.validation.Validated;
import reactor.core.publisher.Flux;
Expand Down Expand Up @@ -63,7 +65,8 @@ public Mono<Offer> random() {
.flatMap(entries -> {
String description = entries.get("description", String.class).orElseThrow(() -> new IllegalStateException("No description"));
BigDecimal price = entries.get("price", BigDecimal.class).orElseThrow(() -> new IllegalStateException("No price"));
return Mono.from(petClient.find(key).toFlowable()).map(pet -> new Offer(pet, description, price));
Flowable<Pet> findPetFlowable = petClient.find(key).toFlowable();
return Mono.from(findPetFlowable).map(pet -> new Offer(pet, description, price));
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petclinic/offers/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
<root level="info">
<appender-ref ref="STDOUT" />
</root>
<!--<logger name="org.particleframework.http.client" level="INFO"/>-->
<logger name="org.particleframework.http.client" level="DEBUG"/>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ import example.api.v1.Offer
import example.api.v1.Pet
import org.particleframework.context.ApplicationContext
import org.particleframework.core.io.socket.SocketUtils
import org.particleframework.http.HttpRequest
import org.particleframework.http.client.RxHttpClient
import org.particleframework.http.client.RxStreamingHttpClient
import org.particleframework.runtime.server.EmbeddedServer
import org.reactivestreams.Subscriber
import org.reactivestreams.Subscription
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Stepwise
import spock.lang.Unroll
import spock.util.concurrent.PollingConditions

import javax.validation.ConstraintViolationException
import java.time.Duration
Expand All @@ -41,6 +47,8 @@ class OffersControllerSpec extends Specification {
@AutoCleanup
EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer,
["consul.client.enabled": false,
"http.client.readTimeout":'3m',
"offers.delay":"10ms", // short delay between offers for testing
"redis.uri":"redis://localhost:${SocketUtils.findAvailableTcpPort()}"]
)

Expand Down Expand Up @@ -108,4 +116,24 @@ class OffersControllerSpec extends Specification {
offer.description == "Friendly Dog"
}

void "test receive random offer"() {
given:
RxStreamingHttpClient rxHttpClient = embeddedServer.applicationContext.createBean(RxStreamingHttpClient, embeddedServer.getURL())

when:
Offer offer = rxHttpClient.jsonStream(HttpRequest.GET("/v1/offers"), Offer)
.blockingFirst()





then: "The offer was read correctly"

offer != null
offer.pet.name == "Harry"
offer.pet.vendor == "Fred"
offer.price == 10.0
offer.description == "Friendly Dog"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
particle.application.name=pets
consul.client.defaultZone=${CONSUL_HOST:localhost}:${CONSUL_PORT:8500}
mongodb.uri=mongodb://${MONGO_HOST:localhost}:${MONGO_PORT:32768}
mongodb.uri=mongodb://${MONGO_HOST:localhost}:${MONGO_PORT:27017}
pets.database.name=petclinic
pets.api.version=v1
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import org.particleframework.core.naming.NameUtils;
import org.particleframework.core.reflect.ClassUtils;
import org.particleframework.core.util.StringUtils;
import org.particleframework.function.DefaultFunctionRegistry;
import org.particleframework.function.DefaultLocalFunctionRegistry;
import org.particleframework.function.FunctionBean;
import org.particleframework.function.FunctionRegistry;
import org.particleframework.function.LocalFunctionRegistry;
import org.particleframework.http.MediaType;
import org.particleframework.inject.BeanDefinition;
import org.particleframework.inject.ExecutableMethod;
Expand All @@ -46,18 +46,18 @@
* @since 1.0
*/
@Singleton
@Replaces(DefaultFunctionRegistry.class)
public class AnnotatedFunctionRouteBuilder extends DefaultRouteBuilder implements ExecutableMethodProcessor<FunctionBean>, FunctionRegistry {
@Replaces(DefaultLocalFunctionRegistry.class)
public class AnnotatedFunctionRouteBuilder extends DefaultRouteBuilder implements ExecutableMethodProcessor<FunctionBean>, LocalFunctionRegistry {


private final FunctionRegistry functionRegistry;
private final LocalFunctionRegistry localFunctionRegistry;

public AnnotatedFunctionRouteBuilder(
ExecutionHandleLocator executionHandleLocator,
UriNamingStrategy uriNamingStrategy,
ConversionService<?> conversionService) {
super(executionHandleLocator, uriNamingStrategy, conversionService);
this.functionRegistry = new DefaultFunctionRegistry();
this.localFunctionRegistry = new DefaultLocalFunctionRegistry();
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -102,39 +102,39 @@ else if(Supplier.class.isAssignableFrom(declaringType)) {
.acceptAll();
}
}
((ExecutableMethodProcessor)functionRegistry).process(beanDefinition, method);
((ExecutableMethodProcessor) localFunctionRegistry).process(beanDefinition, method);
}
}
}


@Override
public <T, R> Optional<? extends ExecutableMethod<T, R>> findFirst() {
return functionRegistry.findFirst();
return localFunctionRegistry.findFirst();
}

@Override
public <T, R> Optional<? extends ExecutableMethod<T, R>> find(String name) {
return functionRegistry.find(name);
return localFunctionRegistry.find(name);
}

@Override
public <T> Optional<ExecutableMethod<Supplier<T>, T>> findSupplier(String name) {
return functionRegistry.findSupplier(name);
return localFunctionRegistry.findSupplier(name);
}

@Override
public <T> Optional<ExecutableMethod<Consumer<T>, Void>> findConsumer(String name) {
return functionRegistry.findConsumer(name);
return localFunctionRegistry.findConsumer(name);
}

@Override
public <T, R> Optional<ExecutableMethod<java.util.function.Function<T, R>, R>> findFunction(String name) {
return functionRegistry.findFunction(name);
return localFunctionRegistry.findFunction(name);
}

@Override
public <T, U, R> Optional<ExecutableMethod<BiFunction<T, U, R>, R>> findBiFunction(String name) {
return functionRegistry.findBiFunction(name);
return localFunctionRegistry.findBiFunction(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import okhttp3.Request
import okhttp3.RequestBody
import org.particleframework.context.ApplicationContext
import org.particleframework.function.FunctionBean
import org.particleframework.function.FunctionRegistry
import org.particleframework.function.LocalFunctionRegistry
import org.particleframework.http.HttpHeaders
import org.particleframework.http.HttpStatus
import org.particleframework.runtime.server.EmbeddedServer
Expand All @@ -39,7 +39,7 @@ class WebFunctionSpec extends Specification {

void "test the function registry"() {
given:
FunctionRegistry registry = ApplicationContext.run(FunctionRegistry)
LocalFunctionRegistry registry = ApplicationContext.run(LocalFunctionRegistry)

expect:
registry.findConsumer("consumer/string").isPresent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@
import java.util.stream.Stream;

/**
* <p>Default implementation of the {@link FunctionRegistry} interface</p>
* <p>Default implementation of the {@link LocalFunctionRegistry} interface</p>
*
* @author Graeme Rocher
* @since 1.0
*/
@Singleton
public class DefaultFunctionRegistry implements ExecutableMethodProcessor<FunctionBean>, FunctionRegistry, MediaTypeCodecRegistry {
public class DefaultLocalFunctionRegistry implements ExecutableMethodProcessor<FunctionBean>, LocalFunctionRegistry, MediaTypeCodecRegistry {
private final Map<String, ExecutableMethod<?,?>> consumers = new LinkedHashMap<>(1);
private final Map<String, ExecutableMethod<?,?>> functions = new LinkedHashMap<>(1);
private final Map<String, ExecutableMethod<?,?>> biFunctions= new LinkedHashMap<>(1);
private final Map<String, ExecutableMethod<?,?>> suppliers = new LinkedHashMap<>(1);
private final MediaTypeCodecRegistry decoderRegistry;

public DefaultFunctionRegistry(MediaTypeCodec...decoders) {
public DefaultLocalFunctionRegistry(MediaTypeCodec...decoders) {
this.decoderRegistry = MediaTypeCodecRegistry.of(decoders);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
import java.util.function.Supplier;

/**
* A registry of defined {@link FunctionBean} instances
* A registry of defined {@link FunctionBean} instances containing within the current running application.
*
* @author Graeme Rocher
* @since 1.0
*/
public interface FunctionRegistry {
public interface LocalFunctionRegistry {

/**
* The name of the default function name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.particleframework.context.ApplicationContext;
import org.particleframework.context.env.Environment;
import org.particleframework.context.env.PropertySource;
import org.particleframework.function.FunctionRegistry;
import org.particleframework.function.LocalFunctionRegistry;
import org.particleframework.inject.ExecutableMethod;

import javax.annotation.Nullable;
Expand All @@ -32,18 +32,18 @@
*/
class AbstractExecutor<C> {
/**
* Resolve a function from the {@link FunctionRegistry}
* @param functionRegistry The {@link FunctionRegistry}
* Resolve a function from the {@link LocalFunctionRegistry}
* @param localFunctionRegistry The {@link LocalFunctionRegistry}
* @param functionName The function name
* @return The method
*/
protected ExecutableMethod<Object, Object> resolveFunction(FunctionRegistry functionRegistry, String functionName) {
protected ExecutableMethod<Object, Object> resolveFunction(LocalFunctionRegistry localFunctionRegistry, String functionName) {
Optional<? extends ExecutableMethod<Object, Object>> registeredMethod;
if(functionName == null) {
registeredMethod = functionRegistry.findFirst();
registeredMethod = localFunctionRegistry.findFirst();
}
else {
registeredMethod = functionRegistry.find(functionName);
registeredMethod = localFunctionRegistry.find(functionName);
}
return registeredMethod
.orElseThrow(() -> new IllegalStateException("No function found for name: " + functionName));
Expand All @@ -55,7 +55,7 @@ protected ExecutableMethod<Object, Object> resolveFunction(FunctionRegistry func
* @return The function name
*/
protected String resolveFunctionName(Environment env) {
return env.getProperty(FunctionRegistry.FUNCTION_NAME, String.class, (String)null);
return env.getProperty(LocalFunctionRegistry.FUNCTION_NAME, String.class, (String)null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/
package org.particleframework.function.executor;

import org.particleframework.function.LocalFunctionRegistry;

/**
* A class that executes the configured {@link org.particleframework.function.FunctionRegistry#FUNCTION_NAME} for the given inputs and outputs
* A class that executes the configured {@link LocalFunctionRegistry#FUNCTION_NAME} for the given inputs and outputs
*
* @author Graeme Rocher
* @since 1.0
Expand Down
Loading

0 comments on commit 66d7acc

Please sign in to comment.