Merge branch 'eugenp:master' into BAEL-5146-Validate-Serialization
This commit is contained in:
commit
c0443cbd1c
|
@ -12,3 +12,4 @@
|
|||
- [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency)
|
||||
- [Why Missing Annotations Don’t Cause ClassNotFoundException](https://www.baeldung.com/classnotfoundexception-missing-annotation)
|
||||
- [Valid @SuppressWarnings Warning Names](https://www.baeldung.com/java-suppresswarnings-valid-names)
|
||||
- [Get a Field’s Annotations Using Reflection](https://www.baeldung.com/java-get-field-annotations)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Generate a WAR File in Maven](https://www.baeldung.com/maven-generate-war-file)
|
|
@ -16,46 +16,15 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-cassandra</artifactId>
|
||||
<version>${org.springframework.data.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-cassandra</artifactId>
|
||||
<version>${spring-boot-starter-data-cassandra.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
|
@ -91,17 +60,10 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.datastax.cassandra</groupId>
|
||||
<artifactId>cassandra-driver-core</artifactId>
|
||||
<version>${cassandra-driver-core.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<org.springframework.data.version>1.3.2.RELEASE</org.springframework.data.version>
|
||||
<cassandra-driver-core.version>2.1.5</cassandra-driver-core.version>
|
||||
<spring-boot-starter-data-cassandra.version>1.3.2.RELEASE</spring-boot-starter-data-cassandra.version>
|
||||
<cassandra-unit-spring.version>2.1.9.2</cassandra-unit-spring.version>
|
||||
<cassandra-unit-shaded.version>2.1.9.2</cassandra-unit-shaded.version>
|
||||
<hector-core.version>2.0-0</hector-core.version>
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate)
|
||||
- [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing)
|
||||
- [Using a List of Values in a JdbcTemplate IN Clause](https://www.baeldung.com/spring-jdbctemplate-in-list)
|
||||
- [Obtaining Auto-generated Keys in Spring JDBC](https://www.baeldung.com/spring-jdbc-autogenerated-keys)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
- [Sorting with JPA](https://www.baeldung.com/jpa-sort)
|
||||
- [Self-Contained Testing Using an In-Memory Database](https://www.baeldung.com/spring-jpa-test-in-memory-database)
|
||||
- [A Guide to Spring AbstractRoutingDatasource](https://www.baeldung.com/spring-abstract-routing-data-source)
|
||||
- [Obtaining Auto-generated Keys in Spring JDBC](https://www.baeldung.com/spring-jdbc-autogenerated-keys)
|
||||
- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations)
|
||||
- More articles: [[next -->]](/spring-jpa-2)
|
||||
|
||||
|
|
|
@ -92,4 +92,8 @@ Then, once again, you can also run both application and DB from docker, using:
|
|||
docker-compose -f src/main/docker/quarkus.yml up
|
||||
```
|
||||
|
||||
Now you have all you need to reproduce the tests with your machine.
|
||||
Now you have all you need to reproduce the tests with your machine.
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Spring Boot vs Quarkus](https://www.baeldung.com/spring-boot-vs-quarkus)
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package com.baeldung.model;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class Quote {
|
||||
|
||||
private Instant ts;
|
||||
private String symbol;
|
||||
private double value;
|
||||
|
||||
public Quote() {}
|
||||
|
||||
|
||||
public Quote(Instant ts, String symbol, double value) {
|
||||
this.ts = ts;
|
||||
this.symbol = symbol;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the ts
|
||||
*/
|
||||
public Instant getTs() {
|
||||
return ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ts the ts to set
|
||||
*/
|
||||
public void setTs(Instant ts) {
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the symbol
|
||||
*/
|
||||
public String getSymbol() {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param symbol the symbol to set
|
||||
*/
|
||||
public void setSymbol(String symbol) {
|
||||
this.symbol = symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((symbol == null) ? 0 : symbol.hashCode());
|
||||
result = prime * result + ((ts == null) ? 0 : ts.hashCode());
|
||||
long temp;
|
||||
temp = Double.doubleToLongBits(value);
|
||||
result = prime * result + (int) (temp ^ (temp >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Quote other = (Quote) obj;
|
||||
if (symbol == null) {
|
||||
if (other.symbol != null)
|
||||
return false;
|
||||
} else if (!symbol.equals(other.symbol))
|
||||
return false;
|
||||
if (ts == null) {
|
||||
if (other.ts != null)
|
||||
return false;
|
||||
} else if (!ts.equals(other.ts))
|
||||
return false;
|
||||
if (Double.doubleToLongBits(value) != Double.doubleToLongBits(other.value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Quote [ts=" + ts + ", symbol=" + symbol + ", value=" + value + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.rxjava.service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import com.baeldung.model.Quote;
|
||||
|
||||
import ratpack.stream.Streams;
|
||||
|
||||
public class QuotesService {
|
||||
|
||||
private final ScheduledExecutorService executorService;
|
||||
private static Random rnd = new Random();
|
||||
private static String[] symbols = new String[] {
|
||||
"MSFT",
|
||||
"ORCL",
|
||||
"GOOG",
|
||||
"AAPL",
|
||||
"CSCO"
|
||||
};
|
||||
|
||||
public QuotesService(ScheduledExecutorService executorService) {
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
public Publisher<Quote> newTicker() {
|
||||
return Streams.periodically(executorService, Duration.ofSeconds(2), (t) -> {
|
||||
|
||||
return randomQuote();
|
||||
});
|
||||
}
|
||||
|
||||
private static Quote randomQuote() {
|
||||
return new Quote (
|
||||
Instant.now(),
|
||||
symbols[rnd.nextInt(symbols.length)],
|
||||
Math.round(rnd.nextDouble()*100)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
package com.baeldung.spring;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.baeldung.model.Quote;
|
||||
import com.baeldung.rxjava.service.QuotesService;
|
||||
|
||||
import groovy.util.logging.Slf4j;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import ratpack.func.Action;
|
||||
import ratpack.handling.Chain;
|
||||
import ratpack.http.ResponseChunks;
|
||||
import ratpack.http.Status;
|
||||
import ratpack.server.ServerConfig;
|
||||
import ratpack.spring.config.EnableRatpack;
|
||||
import ratpack.sse.ServerSentEvents;
|
||||
import ratpack.stream.Streams;
|
||||
import ratpack.stream.TransformablePublisher;
|
||||
import ratpack.websocket.WebSockets;
|
||||
import rx.subscriptions.Subscriptions;
|
||||
|
||||
/**
|
||||
* @author psevestre
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableRatpack
|
||||
public class EmbedRatpackStreamsApp {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EmbedRatpackStreamsApp.class);
|
||||
|
||||
@Autowired
|
||||
private QuotesService quotesService;
|
||||
|
||||
private AtomicLong idSeq = new AtomicLong(0);
|
||||
|
||||
|
||||
@Bean
|
||||
public ScheduledExecutorService executorService() {
|
||||
return Executors.newScheduledThreadPool(1);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public QuotesService quotesService(ScheduledExecutorService executor) {
|
||||
return new QuotesService(executor);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<Chain> quotes() {
|
||||
ServerSentEvents sse = ServerSentEvents.serverSentEvents(quotesService.newTicker(), (evt) -> {
|
||||
evt
|
||||
.id(Long.toString(idSeq.incrementAndGet()))
|
||||
.event("quote")
|
||||
.data( q -> q.toString());
|
||||
});
|
||||
|
||||
return chain -> chain.get("quotes", ctx -> ctx.render(sse));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<Chain> quotesWS() {
|
||||
Publisher<String> pub = Streams.transformable(quotesService.newTicker())
|
||||
.map(Quote::toString);
|
||||
return chain -> chain.get("quotes-ws", ctx -> WebSockets.websocketBroadcast(ctx, pub));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<Chain> uploadFile() {
|
||||
|
||||
return chain -> chain.post("upload", ctx -> {
|
||||
TransformablePublisher<? extends ByteBuf> pub = ctx.getRequest().getBodyStream();
|
||||
pub.subscribe(new Subscriber<ByteBuf>() {
|
||||
private Subscription sub;
|
||||
@Override
|
||||
public void onSubscribe(Subscription sub) {
|
||||
this.sub = sub;
|
||||
sub.request(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(ByteBuf t) {
|
||||
try {
|
||||
int len = t.readableBytes();
|
||||
log.info("Got {} bytes", len);
|
||||
|
||||
// Do something useful with data
|
||||
|
||||
// Request next chunk
|
||||
sub.request(1);
|
||||
}
|
||||
finally {
|
||||
// DO NOT FORGET to RELEASE !
|
||||
t.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
ctx.getResponse().status(500);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
ctx.getResponse().status(202);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<Chain> download() {
|
||||
return chain -> chain.get("download", ctx -> {
|
||||
ctx.getResponse().sendStream(new RandomBytesPublisher(1024,512));
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<Chain> downloadChunks() {
|
||||
return chain -> chain.get("downloadChunks", ctx -> {
|
||||
ctx.render(ResponseChunks.bufferChunks("application/octetstream",
|
||||
new RandomBytesPublisher(1024,512)));
|
||||
});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServerConfig ratpackServerConfig() {
|
||||
return ServerConfig
|
||||
.builder()
|
||||
.findBaseDir("public")
|
||||
.build();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(EmbedRatpackStreamsApp.class, args);
|
||||
}
|
||||
|
||||
|
||||
public static class RandomBytesPublisher implements Publisher<ByteBuf> {
|
||||
|
||||
private int bufCount;
|
||||
private int bufSize;
|
||||
private Random rnd = new Random();
|
||||
|
||||
|
||||
RandomBytesPublisher(int bufCount, int bufSize) {
|
||||
this.bufCount = bufCount;
|
||||
this.bufSize = bufSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(Subscriber<? super ByteBuf> s) {
|
||||
s.onSubscribe(new Subscription() {
|
||||
|
||||
private boolean cancelled = false;
|
||||
private boolean recurse;
|
||||
private long requested = 0;
|
||||
|
||||
@Override
|
||||
public void request(long n) {
|
||||
if ( bufCount == 0 ) {
|
||||
s.onComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
requested += n;
|
||||
if ( recurse ) {
|
||||
return;
|
||||
}
|
||||
|
||||
recurse = true;
|
||||
try {
|
||||
while ( requested-- > 0 && !cancelled && bufCount-- > 0 ) {
|
||||
byte[] data = new byte[bufSize];
|
||||
rnd.nextBytes(data);
|
||||
ByteBuf buf = Unpooled.wrappedBuffer(data);
|
||||
s.onNext(buf);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
recurse = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.baeldung.ratpack;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
// Non-thread safe !!!
|
||||
class CompliantPublisher implements Publisher<Integer> {
|
||||
String name;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CompliantPublisher.class);
|
||||
private long available;
|
||||
|
||||
|
||||
public CompliantPublisher(long available) {
|
||||
this.available = available;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(Subscriber<? super Integer> subscriber) {
|
||||
log.info("subscribe");
|
||||
subscriber.onSubscribe(new CompliantSubscription(subscriber));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class CompliantSubscription implements Subscription {
|
||||
|
||||
private Subscriber<? super Integer> subscriber;
|
||||
private int recurseLevel;
|
||||
private long requested;
|
||||
private boolean cancelled;
|
||||
|
||||
public CompliantSubscription(Subscriber<? super Integer> subscriber) {
|
||||
this.subscriber = subscriber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void request(long n) {
|
||||
log.info("request: requested={}, available={}", n, available);
|
||||
requested += n;
|
||||
if ( recurseLevel > 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
recurseLevel++;
|
||||
for (int i = 0 ; i < (requested) && !cancelled && available > 0 ; i++, available-- ) {
|
||||
subscriber.onNext(i);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.baeldung.ratpack;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class LoggingSubscriber<T> implements Subscriber<T> {
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggingSubscriber.class);
|
||||
|
||||
private Subscription subscription;
|
||||
private long requested;
|
||||
private long received;
|
||||
private CountDownLatch finished = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
log.info("onComplete: sub={}", subscription.hashCode());
|
||||
finished.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
log.error("Error: sub={}, message={}", subscription.hashCode(), t.getMessage(),t);
|
||||
finished.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(T value) {
|
||||
log.info("onNext: sub={}, value={}", subscription.hashCode(), value);
|
||||
this.received++;
|
||||
this.requested++;
|
||||
subscription.request(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Subscription sub) {
|
||||
log.info("onSubscribe: sub={}", sub.hashCode());
|
||||
this.subscription = sub;
|
||||
this.received = 0;
|
||||
this.requested = 1;
|
||||
sub.request(1);
|
||||
}
|
||||
|
||||
|
||||
public long getRequested() {
|
||||
return requested;
|
||||
}
|
||||
|
||||
public long getReceived() {
|
||||
return received;
|
||||
}
|
||||
|
||||
public void block() {
|
||||
try {
|
||||
finished.await(10, TimeUnit.SECONDS);
|
||||
}
|
||||
catch(InterruptedException iex) {
|
||||
throw new RuntimeException(iex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung.ratpack;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class NonCompliantPublisher implements Publisher<Integer> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(NonCompliantPublisher.class);
|
||||
|
||||
@Override
|
||||
public void subscribe(Subscriber<? super Integer> subscriber) {
|
||||
log.info("subscribe");
|
||||
subscriber.onSubscribe(new NonCompliantSubscription(subscriber));
|
||||
}
|
||||
|
||||
private class NonCompliantSubscription implements Subscription {
|
||||
private Subscriber<? super Integer> subscriber;
|
||||
private int recurseLevel = 0;
|
||||
|
||||
public NonCompliantSubscription(Subscriber<? super Integer> subscriber) {
|
||||
this.subscriber = subscriber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void request(long n) {
|
||||
log.info("request: n={}", n);
|
||||
if ( recurseLevel > 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
recurseLevel++;
|
||||
for (int i = 0 ; i < (n + 5) ; i ++ ) {
|
||||
subscriber.onNext(i);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
package com.baeldung.ratpack;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ratpack.exec.ExecResult;
|
||||
import ratpack.func.Action;
|
||||
import ratpack.stream.StreamEvent;
|
||||
import ratpack.stream.Streams;
|
||||
import ratpack.stream.TransformablePublisher;
|
||||
import ratpack.test.exec.ExecHarness;
|
||||
|
||||
public class RatpackStreamsUnitTest {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(RatpackStreamsUnitTest.class);
|
||||
|
||||
@Test
|
||||
public void whenPublish_thenSuccess() {
|
||||
|
||||
Publisher<String> pub = Streams.publish(Arrays.asList("hello", "hello again"));
|
||||
LoggingSubscriber<String> sub = new LoggingSubscriber<String>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void whenYield_thenSuccess() {
|
||||
|
||||
Publisher<String> pub = Streams.yield((t) -> {
|
||||
return t.getRequestNum() < 5 ? "hello" : null;
|
||||
});
|
||||
|
||||
LoggingSubscriber<String> sub = new LoggingSubscriber<String>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
assertEquals(5, sub.getReceived());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenPeriodic_thenSuccess() {
|
||||
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
|
||||
Publisher<String> pub = Streams.periodically(executor, Duration.ofSeconds(1), (t) -> {
|
||||
return t < 5 ? String.format("hello %d",t): null;
|
||||
});
|
||||
|
||||
LoggingSubscriber<String> sub = new LoggingSubscriber<String>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
assertEquals(5, sub.getReceived());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMap_thenSuccess() throws Exception {
|
||||
|
||||
TransformablePublisher<String> pub = Streams.yield( t -> {
|
||||
return t.getRequestNum() < 5 ? t.getRequestNum() : null;
|
||||
})
|
||||
.map(v -> String.format("item %d", v));
|
||||
|
||||
ExecResult<List<String>> result = ExecHarness.yieldSingle((c) -> pub.toList() );
|
||||
assertTrue("should succeed", result.isSuccess());
|
||||
assertEquals("should have 5 items",5,result.getValue().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNonCompliantPublisherWithBuffer_thenSuccess() throws Exception {
|
||||
|
||||
TransformablePublisher<Integer> pub = Streams.transformable(new NonCompliantPublisher())
|
||||
.wiretap(new LoggingAction("before buffer"))
|
||||
.buffer()
|
||||
.wiretap(new LoggingAction("after buffer"))
|
||||
.take(1);
|
||||
|
||||
LoggingSubscriber<Integer> sub = new LoggingSubscriber<>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNonCompliantPublisherWithoutBuffer_thenSuccess() throws Exception {
|
||||
TransformablePublisher<Integer> pub = Streams.transformable(new NonCompliantPublisher())
|
||||
.wiretap(new LoggingAction(""))
|
||||
.take(1);
|
||||
|
||||
LoggingSubscriber<Integer> sub = new LoggingSubscriber<>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCompliantPublisherWithoutBatch_thenSuccess() throws Exception {
|
||||
|
||||
TransformablePublisher<Integer> pub = Streams.transformable(new CompliantPublisher(10))
|
||||
.wiretap(new LoggingAction(""));
|
||||
|
||||
LoggingSubscriber<Integer> sub = new LoggingSubscriber<>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCompliantPublisherWithBatch_thenSuccess() throws Exception {
|
||||
|
||||
TransformablePublisher<Integer> pub = Streams.transformable(new CompliantPublisher(10))
|
||||
.wiretap(new LoggingAction("before batch"))
|
||||
.batch(5, Action.noop())
|
||||
.wiretap(new LoggingAction("after batch"));
|
||||
|
||||
LoggingSubscriber<Integer> sub = new LoggingSubscriber<>();
|
||||
pub.subscribe(sub);
|
||||
sub.block();
|
||||
}
|
||||
|
||||
private static class LoggingAction implements Action<StreamEvent<Integer>>{
|
||||
private final String label;
|
||||
|
||||
public LoggingAction(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(StreamEvent<Integer> e) throws Exception {
|
||||
log.info("{}: event={}", label,e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package com.baeldung.jdbc.autogenkey.repository;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.GeneratedKeyHolder;
|
||||
import org.springframework.jdbc.support.KeyHolder;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class MessageRepositoryJDBCTemplate {
|
||||
|
||||
@Autowired
|
||||
JdbcTemplate jdbcTemplate;
|
||||
|
||||
final String INSERT_MESSAGE_SQL = "insert into sys_message (message) values(?) ";
|
||||
|
||||
public long insert(final String message) {
|
||||
|
||||
KeyHolder keyHolder = new GeneratedKeyHolder();
|
||||
|
||||
jdbcTemplate.update(connection -> {
|
||||
PreparedStatement ps = connection.prepareStatement(INSERT_MESSAGE_SQL);
|
||||
ps.setString(1, message);
|
||||
return ps;
|
||||
}, keyHolder);
|
||||
|
||||
return (long) keyHolder.getKey();
|
||||
}
|
||||
|
||||
final String SELECT_BY_ID = "select message from sys_message where id = ?";
|
||||
|
||||
public String getMessageById(long id) {
|
||||
return this.jdbcTemplate.queryForObject(SELECT_BY_ID, String.class, new Object[] { id });
|
||||
}
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package com.baeldung.jdbc.autogenkey.repository;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class MessageRepositorySimpleJDBCInsert {
|
||||
|
||||
SimpleJdbcInsert messageInsert;
|
||||
|
||||
@Autowired
|
||||
public MessageRepositorySimpleJDBCInsert(DataSource dataSource) {
|
||||
messageInsert = new SimpleJdbcInsert(dataSource).withTableName("sys_message").usingGeneratedKeyColumns("id");
|
||||
}
|
||||
|
||||
public long insert(String message) {
|
||||
Map<String, Object> parameters = new HashMap<String, Object>(1);
|
||||
parameters.put("message", message);
|
||||
Number newId = messageInsert.executeAndReturnKey(parameters);
|
||||
return (long) newId;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
|
||||
spring.datasource.initialize=true
|
||||
spring.datasource.schema=classpath:autogenkey-schema.sql
|
|
@ -1,5 +0,0 @@
|
|||
CREATE TABLE IF NOT EXISTS sys_message (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
message varchar(100) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
|
@ -1,55 +0,0 @@
|
|||
package com.baeldung.jdbc.autogenkey;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.baeldung.jdbc.autogenkey.repository.MessageRepositoryJDBCTemplate;
|
||||
import com.baeldung.jdbc.autogenkey.repository.MessageRepositorySimpleJDBCInsert;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@Ignore
|
||||
public class GetAutoGenKeyByJDBCIntTest {
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@PropertySource("classpath:autogenkey-db.properties")
|
||||
@ComponentScan(basePackages = { "com.baeldung.jdbc.autogenkey.repository" })
|
||||
public static class SpringConfig {
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
MessageRepositorySimpleJDBCInsert messageRepositorySimpleJDBCInsert;
|
||||
|
||||
@Autowired
|
||||
MessageRepositoryJDBCTemplate messageRepositoryJDBCTemplate;
|
||||
|
||||
final String MESSAGE_CONTENT = "Test";
|
||||
|
||||
@Test
|
||||
public void insertJDBC_whenLoadMessageByKey_thenGetTheSameMessage() {
|
||||
long key = messageRepositoryJDBCTemplate.insert(MESSAGE_CONTENT);
|
||||
String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key);
|
||||
|
||||
assertEquals(MESSAGE_CONTENT, loadedMessage);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertSimpleInsert_whenLoadMessageKey_thenGetTheSameMessage() {
|
||||
long key = messageRepositorySimpleJDBCInsert.insert(MESSAGE_CONTENT);
|
||||
String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key);
|
||||
|
||||
assertEquals(MESSAGE_CONTENT, loadedMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -175,6 +175,7 @@
|
|||
<!-- util -->
|
||||
<guava.version>19.0</guava.version>
|
||||
<!-- Maven plugins -->
|
||||
<maven-war-plugin.version>3.2.2</maven-war-plugin.version>
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
package com.baeldung.web.interceptor;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class LoggerInterceptor extends HandlerInterceptorAdapter {
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
public class LoggerInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(LoggerInterceptor.class);
|
||||
|
||||
|
@ -50,7 +52,8 @@ public class LoggerInterceptor extends HandlerInterceptorAdapter {
|
|||
if (posted.length() > 1)
|
||||
posted.append("&");
|
||||
final String curr = (String) e.nextElement();
|
||||
posted.append(curr).append("=");
|
||||
posted.append(curr)
|
||||
.append("=");
|
||||
if (curr.contains("password") || curr.contains("answer") || curr.contains("pwd")) {
|
||||
posted.append("*****");
|
||||
} else {
|
||||
|
|
|
@ -8,10 +8,10 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
public class SessionTimerInterceptor extends HandlerInterceptorAdapter {
|
||||
public class SessionTimerInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(SessionTimerInterceptor.class);
|
||||
|
||||
|
@ -30,7 +30,8 @@ public class SessionTimerInterceptor extends HandlerInterceptorAdapter {
|
|||
request.setAttribute("executionTime", startTime);
|
||||
if (UserInterceptor.isUserLogged()) {
|
||||
session = request.getSession();
|
||||
log.info("Time since last request in this session: {} ms", System.currentTimeMillis() - request.getSession().getLastAccessedTime());
|
||||
log.info("Time since last request in this session: {} ms", System.currentTimeMillis() - request.getSession()
|
||||
.getLastAccessedTime());
|
||||
if (System.currentTimeMillis() - session.getLastAccessedTime() > MAX_INACTIVE_SESSION_TIME) {
|
||||
log.warn("Logging out, due to inactive session");
|
||||
SecurityContextHolder.clearContext();
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
package com.baeldung.web.interceptor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.SmartView;
|
||||
import org.springframework.web.servlet.View;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
public class UserInterceptor extends HandlerInterceptorAdapter {
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.SmartView;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
public class UserInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(UserInterceptor.class);
|
||||
|
||||
|
@ -44,7 +44,9 @@ public class UserInterceptor extends HandlerInterceptorAdapter {
|
|||
*/
|
||||
private void addToModelUserDetails(HttpSession session) {
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
String loggedUsername = SecurityContextHolder.getContext()
|
||||
.getAuthentication()
|
||||
.getName();
|
||||
session.setAttribute("username", loggedUsername);
|
||||
log.info("user(" + loggedUsername + ") session : " + session);
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
|
@ -56,7 +58,9 @@ public class UserInterceptor extends HandlerInterceptorAdapter {
|
|||
*/
|
||||
private void addToModelUserDetails(ModelAndView model) {
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
String loggedUsername = SecurityContextHolder.getContext()
|
||||
.getAuthentication()
|
||||
.getName();
|
||||
model.addObject("loggedUsername", loggedUsername);
|
||||
log.trace("session : " + model.getModel());
|
||||
log.info("================= addToModelUserDetails ============================");
|
||||
|
@ -76,7 +80,10 @@ public class UserInterceptor extends HandlerInterceptorAdapter {
|
|||
|
||||
public static boolean isUserLogged() {
|
||||
try {
|
||||
return !SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser");
|
||||
return !SecurityContextHolder.getContext()
|
||||
.getAuthentication()
|
||||
.getName()
|
||||
.equals("anonymousUser");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue