This commit is contained in:
BoykoAlex
2018-03-08 11:28:49 -05:00
18 changed files with 418 additions and 222 deletions

View File

@@ -1,7 +1,8 @@
#!/bin/bash
set -e
set -e
# set -x
workdir=$(pwd)
outdir=${workdir}/out
out=${workdir}/out
git config --global user.email "kdevolder@pivotal.io"
git config --global user.name "Kris De Volder"
@@ -15,5 +16,6 @@ for package in atom-* ; do
cd ${package}
tag=v$(cat package.json | jq -r ".version")
echo "Tag: ${tag}"
git tag $tag
done

View File

@@ -4,6 +4,7 @@ image_resource:
source:
repository: kdvolder/sts4-build-env
inputs:
- name: sts4
- name: atom-bosh
- name: atom-concourse
- name: atom-spring-boot

View File

@@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
/**
* @author Martin Lippert
*/
public enum MediaTypeMapping {
TEXT_PLAIN("text/plain"),
APPLICATION_JSON("application/json"),
APPLICATION_STREAM_JSON("application/stream+json");
private String mediaType;
private MediaTypeMapping(String mediaType) {
this.mediaType = mediaType;
}
public String getMediaType() {
return mediaType;
}
}

View File

@@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
/**
* @author Martin Lippert
*/
public class WebfluxAcceptTypeFinder extends ASTVisitor {
private String acceptType;
public WebfluxAcceptTypeFinder() {
}
public String getAcceptType() {
return acceptType;
}
@Override
public boolean visit(MethodInvocation node) {
boolean visitChildren = true;
IMethodBinding methodBinding = node.resolveMethodBinding();
if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
String name = methodBinding.getName();
if (name != null && WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(name)) {
acceptType = WebfluxUtils.extractSimpleNameArgument(node);
}
}
if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) {
visitChildren = false;
}
return visitChildren;
}
}

View File

@@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
/**
* @author Martin Lippert
*/
public class WebfluxContentTypeFinder extends ASTVisitor {
private String contentType;
private ASTNode root;
public WebfluxContentTypeFinder(ASTNode root) {
this.root = root;
}
public String getContentType() {
return contentType;
}
@Override
public boolean visit(MethodInvocation node) {
boolean visitChildren = true;
if (node != this.root) {
IMethodBinding methodBinding = node.resolveMethodBinding();
if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
String name = methodBinding.getName();
if (name != null && WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(name)) {
contentType = WebfluxUtils.extractSimpleNameArgument(node);
}
}
if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) {
visitChildren = false;
}
}
return visitChildren;
}
}

View File

@@ -71,7 +71,14 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider {
CodeLens codeLens = new CodeLens();
codeLens.setRange(document.toRange(node.getName().getStartPosition(), node.getName().getLength()));
codeLens.setCommand(new Command(handlerInfo.getSymbol(), null));
String codeLensCommand = handlerInfo.getHttpMethod() != null ? handlerInfo.getHttpMethod() + " " : "";
codeLensCommand += handlerInfo.getPath();
codeLensCommand += handlerInfo.getAcceptType() != null ? " - Accept: " + getMediaType(handlerInfo.getAcceptType()) : "";
codeLensCommand += handlerInfo.getContentType() != null ? " - Content-Type: " + getMediaType(handlerInfo.getContentType()) : "";
codeLens.setCommand(new Command(codeLensCommand, null));
resultAccumulator.add(codeLens);
} catch (BadLocationException e) {
@@ -81,5 +88,19 @@ public class WebfluxHandlerCodeLensProvider implements CodeLensProvider {
}
}
}
protected String getMediaType(String handlerInfo) {
if (handlerInfo == null) {
return null;
}
try {
MediaTypeMapping mediaType = MediaTypeMapping.valueOf(handlerInfo);
return mediaType.getMediaType();
}
catch (IllegalArgumentException e) {
return handlerInfo;
}
}
}

View File

@@ -15,18 +15,22 @@ package org.springframework.ide.vscode.boot.java.requestmapping;
*/
public class WebfluxHandlerInformation {
private final String symbol;
private String handlerClass;
private String handlerMethod;
private final String handlerClass;
private final String handlerMethod;
public WebfluxHandlerInformation(String symbol, String handlerClass, String handlerMethod) {
this.symbol = symbol;
private final String path;
private final String httpMethod;
private final String contentType;
private final String acceptType;
public WebfluxHandlerInformation(String handlerClass, String handlerMethod, String path, String httpMethod, String contentType, String acceptType) {
this.handlerClass = handlerClass;
this.handlerMethod = handlerMethod;
}
public String getSymbol() {
return symbol;
this.path = path;
this.httpMethod = httpMethod;
this.contentType = contentType;
this.acceptType = acceptType;
}
public String getHandlerClass() {
@@ -36,5 +40,21 @@ public class WebfluxHandlerInformation {
public String getHandlerMethod() {
return handlerMethod;
}
public String getPath() {
return path;
}
public String getHttpMethod() {
return httpMethod;
}
public String getContentType() {
return contentType;
}
public String getAcceptType() {
return acceptType;
}
}

View File

@@ -10,13 +10,10 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.requestmapping;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
/**
* @author Martin Lippert
@@ -47,7 +44,7 @@ public class WebfluxMethodFinder extends ASTVisitor {
method = name;
}
else if (name != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(name)) {
method = extractMethodValue(node);
method = WebfluxUtils.extractQualifiedNameArgument(node);
}
}
@@ -58,18 +55,4 @@ public class WebfluxMethodFinder extends ASTVisitor {
return visitChildren;
}
private String extractMethodValue(MethodInvocation node) {
List<?> arguments = node.arguments();
if (arguments != null && arguments.size() > 0) {
Object object = arguments.get(0);
if (object instanceof QualifiedName) {
QualifiedName qualifiedName = (QualifiedName) object;
if (qualifiedName.getName() != null) {
return qualifiedName.getName().toString();
}
}
}
return null;
}
}

View File

@@ -41,7 +41,7 @@ public class WebfluxPathFinder extends ASTVisitor {
if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
String name = methodBinding.getName();
if (name != null && WebfluxUtils.REQUEST_PREDICATE_ALL_PATH_METHODS.contains(name)) {
path = WebfluxUtils.extractPath(node);
path = WebfluxUtils.extractStringLiteralArgument(node);
}
}

View File

@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.requestmapping;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
@@ -33,6 +34,9 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
/**
* @author Martin Lippert
*/
@@ -87,10 +91,12 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
}
protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List<EnhancedSymbolInformation> result) {
String foundPath = extractPathFromRouterFunction(node);
String path = extractPath(node, foundPath);
String path = extractPath(node);
String httpMethod = extractMethod(node);
String contentType = extractContentType(node);
String acceptType = extractAcceptType(node);
int methodNameStart = node.getName().getStartPosition();
int invocationStart = node.getStartPosition();
@@ -99,7 +105,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart)));
String label = "@" + (path.startsWith("/") ? path : ("/" + path)) + (httpMethod == null || httpMethod.isEmpty() ? "" : " -- " + httpMethod);
WebfluxHandlerInformation handler = extractHandlerInformation(node, label);
WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethod, contentType, acceptType);
result.add(new EnhancedSymbolInformation(new SymbolInformation(label, SymbolKind.Interface, location), handler));
} catch (BadLocationException e) {
@@ -108,19 +114,102 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
}
}
private String extractPathFromRouterFunction(MethodInvocation routerInvocation) {
private String extractPath(MethodInvocation routerInvocation) {
WebfluxPathFinder pathFinder = new WebfluxPathFinder(routerInvocation);
routerInvocation.accept(pathFinder);
String path = pathFinder.getPath();
if (path == null) path = "";
return path;
return extractNestedValue(routerInvocation, path, (methodInvocationPathPrefix) -> {
IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding();
String methodName = methodBinding.getName();
if (WebfluxUtils.REQUEST_PREDICATE_PATH_METHOD.equals(methodName)) {
String additionalPath = WebfluxUtils.extractStringLiteralArgument(methodInvocationPathPrefix.getT1());
if (additionalPath != null && additionalPath.length() > 0) {
return additionalPath + methodInvocationPathPrefix.getT2();
}
}
return methodInvocationPathPrefix.getT2();
});
}
private String extractPath(ASTNode node, String path) {
private String extractMethod(MethodInvocation routerInvocation) {
WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation);
routerInvocation.accept(methodFinder);
String method = methodFinder.getMethod();
return extractNestedValue(routerInvocation, method, (methodInvocationPathPrefix) -> {
IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding();
String methodName = methodBinding.getName();
if (WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(methodName)) {
String newMethod = WebfluxUtils.extractStringLiteralArgument(methodInvocationPathPrefix.getT1());
if (method == null) {
return newMethod;
}
}
return methodInvocationPathPrefix.getT2();
});
}
private String extractAcceptType(MethodInvocation routerInvocation) {
String acceptType = null;
WebfluxAcceptTypeFinder acceptTypeFinder = new WebfluxAcceptTypeFinder();
List<?> arguments = routerInvocation.arguments();
for (Object argument : arguments) {
if (argument != null && argument instanceof ASTNode) {
((ASTNode)argument).accept(acceptTypeFinder);
if (acceptTypeFinder.getAcceptType() != null) {
acceptType = acceptTypeFinder.getAcceptType();
}
}
}
return extractNestedValue(routerInvocation, acceptType, (methodInvocationPathPrefix) -> {
IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding();
String methodName = methodBinding.getName();
if (WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(methodName)) {
String newAcceptType = WebfluxUtils.extractSimpleNameArgument(methodInvocationPathPrefix.getT1());
if (newAcceptType != null) {
return newAcceptType;
}
}
return methodInvocationPathPrefix.getT2();
});
}
private String extractContentType(MethodInvocation routerInvocation) {
WebfluxContentTypeFinder contentTypeFinder = new WebfluxContentTypeFinder(routerInvocation);
routerInvocation.accept(contentTypeFinder);
String contentType = contentTypeFinder.getContentType();
return extractNestedValue(routerInvocation, contentType, (methodInvocationPathPrefix) -> {
IMethodBinding methodBinding = methodInvocationPathPrefix.getT1().resolveMethodBinding();
String methodName = methodBinding.getName();
if (WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(methodName)) {
String newContentType = WebfluxUtils.extractSimpleNameArgument(methodInvocationPathPrefix.getT1());
if (contentType == null) {
return newContentType;
}
}
return methodInvocationPathPrefix.getT2();
});
}
private String extractNestedValue(ASTNode node, String value, Function<Tuple2<MethodInvocation, String>, String> extractor) {
if (node == null || node instanceof TypeDeclaration) {
return path;
return value;
}
if (node instanceof MethodInvocation) {
@@ -129,39 +218,22 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
if (WebfluxUtils.ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
String name = methodBinding.getName();
if ("nest".equals(name)) {
if (WebfluxUtils.REQUEST_PREDICATE_NEST_METHOD.equals(name)) {
List<?> arguments = methodInvocation.arguments();
for (Object argument : arguments) {
if (argument instanceof MethodInvocation) {
MethodInvocation nestedMethod = (MethodInvocation) argument;
IMethodBinding nestedMethodBinding = nestedMethod.resolveMethodBinding();
String nestedMethodName = nestedMethodBinding.getName();
if ("path".equals(nestedMethodName)) {
String additionalPath = WebfluxUtils.extractPath(nestedMethod);
if (additionalPath != null && additionalPath.length() > 0) {
path = additionalPath + path;
}
}
value = extractor.apply(Tuples.of(nestedMethod, value));
}
}
}
}
}
return extractPath(node.getParent(), path);
return extractNestedValue(node.getParent(), value, extractor);
}
private String extractMethod(MethodInvocation routerInvocation) {
WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation);
routerInvocation.accept(methodFinder);
String method = methodFinder.getMethod();
return method;
}
private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String symbol) {
private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, String httpMethod, String contentType, String acceptType) {
List<?> arguments = node.arguments();
if (arguments != null) {
@@ -177,7 +249,7 @@ public class WebfluxRouterSymbolProvider implements SymbolProvider {
String handlerMethod = methodBinding.getMethodDeclaration().toString();
if (handlerMethod != null) handlerMethod = handlerMethod.trim();
return new WebfluxHandlerInformation(symbol, handlerClass, handlerMethod);
return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, httpMethod, contentType, acceptType);
}
}
}

View File

@@ -17,6 +17,8 @@ import java.util.Set;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
/**
@@ -30,12 +32,15 @@ public class WebfluxUtils {
public static final String REQUEST_PREDICATE_PATH_METHOD = "path";
public static final String REQUEST_PREDICATE_METHOD_METHOD = "method";
public static final String REQUEST_PREDICATE_ACCEPT_TYPE_METHOD = "accept";
public static final String REQUEST_PREDICATE_CONTENT_TYPE_METHOD = "contentType";
public static final String REQUEST_PREDICATE_NEST_METHOD = "nest";
public static final Set<String> REQUEST_PREDICATE_HTTPMETHOD_METHODS = new HashSet<>(Arrays.asList("GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS"));
public static final Set<String> REQUEST_PREDICATE_ALL_PATH_METHODS = new HashSet<>(Arrays.asList(REQUEST_PREDICATE_PATH_METHOD, "GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS"));
public static String extractPath(MethodInvocation node) {
public static String extractStringLiteralArgument(MethodInvocation node) {
List<?> arguments = node.arguments();
if (arguments != null && arguments.size() > 0) {
Object object = arguments.get(0);
@@ -47,6 +52,36 @@ public class WebfluxUtils {
return null;
}
public static String extractQualifiedNameArgument(MethodInvocation node) {
List<?> arguments = node.arguments();
if (arguments != null && arguments.size() > 0) {
Object object = arguments.get(0);
if (object instanceof QualifiedName) {
QualifiedName qualifiedName = (QualifiedName) object;
if (qualifiedName.getName() != null) {
return qualifiedName.getName().toString();
}
}
}
return null;
}
public static String extractSimpleNameArgument(MethodInvocation node) {
List<?> arguments = node.arguments();
if (arguments != null && arguments.size() > 0) {
Object object = arguments.get(0);
if (object instanceof SimpleName) {
SimpleName name = (SimpleName) object;
if (name.getFullyQualifiedName() != null) {
return name.getFullyQualifiedName().toString();
}
}
}
return null;
}
public static boolean isRouteMethodInvocation(IMethodBinding methodBinding) {
if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
String name = methodBinding.getName();

View File

@@ -53,10 +53,10 @@ public class WebFluxCodeLensProviderTest {
assertEquals(4, codeLenses.size());
assertTrue(containsCodeLens(codeLenses, "@/hello -- GET", 25, 29, 25, 34));
assertTrue(containsCodeLens(codeLenses, "@/echo -- POST", 30, 29, 30, 33));
assertTrue(containsCodeLens(codeLenses, "@/quotes -- GET", 35, 29, 35, 41));
assertTrue(containsCodeLens(codeLenses, "@/quotes -- GET", 41, 29, 41, 40));
assertTrue(containsCodeLens(codeLenses, "GET /hello - Accept: text/plain", 25, 29, 25, 34));
assertTrue(containsCodeLens(codeLenses, "POST /echo - Accept: text/plain - Content-Type: text/plain", 30, 29, 30, 33));
assertTrue(containsCodeLens(codeLenses, "GET /quotes - Accept: application/stream+json", 35, 29, 35, 41));
assertTrue(containsCodeLens(codeLenses, "GET /quotes - Accept: application/json", 41, 29, 41, 40));
}
private boolean containsCodeLens(List<? extends CodeLens> codeLenses, String commandTitle, int startLine, int startPosition, int endLine, int endPosition) {

View File

@@ -46,8 +46,8 @@ public class WebFluxMappingSymbolProviderTest {
String docUri = directory.toPath().resolve("src/main/java/org/test/UserController.java").toUri().toString();
List<? extends SymbolInformation> symbols = getSymbols(docUri);
assertEquals(4, symbols.size());
assertTrue(containsSymbol(symbols, "@/users", docUri, 19, 1, 19, 74));
assertTrue(containsSymbol(symbols, "@/users/{username}", docUri, 24, 1, 24, 85));
assertTrue(containsSymbol(symbols, "@/users", docUri, 13, 1, 13, 74));
assertTrue(containsSymbol(symbols, "@/users/{username}", docUri, 18, 1, 18, 85));
List<? extends Object> addons = getAdditionalInformation(docUri);
assertNull(addons);
@@ -69,23 +69,35 @@ public class WebFluxMappingSymbolProviderTest {
List<? extends Object> addons = getAdditionalInformation(docUri);
assertEquals(4, addons.size());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "@/hello -- GET").get(0);
assertEquals("@/hello -- GET", handlerInfo1.getSymbol());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/hello", "GET").get(0);
assertEquals("/hello", handlerInfo1.getPath());
assertEquals("GET", handlerInfo1.getHttpMethod());
assertNull(handlerInfo1.getContentType());
assertEquals("TEXT_PLAIN", handlerInfo1.getAcceptType());
assertEquals("org.test.QuoteHandler", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> hello(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "@/echo -- POST").get(0);
assertEquals("@/echo -- POST", handlerInfo2.getSymbol());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/echo", "POST").get(0);
assertEquals("/echo", handlerInfo2.getPath());
assertEquals("POST", handlerInfo2.getHttpMethod());
assertEquals("TEXT_PLAIN", handlerInfo2.getContentType());
assertEquals("TEXT_PLAIN", handlerInfo2.getAcceptType());
assertEquals("org.test.QuoteHandler", handlerInfo2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> echo(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "@/quotes -- GET").get(0);
assertEquals("@/quotes -- GET", handlerInfo3.getSymbol());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/quotes", "GET").get(0);
assertEquals("/quotes", handlerInfo3.getPath());
assertEquals("GET", handlerInfo3.getHttpMethod());
assertNull(handlerInfo3.getContentType());
assertEquals("APPLICATION_STREAM_JSON", handlerInfo3.getAcceptType());
assertEquals("org.test.QuoteHandler", handlerInfo3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> streamQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod());
WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "@/quotes -- GET").get(1);
assertEquals("@/quotes -- GET", handlerInfo4.getSymbol());
WebfluxHandlerInformation handlerInfo4 = getWebfluxHandler(addons, "/quotes", "GET").get(1);
assertEquals("/quotes", handlerInfo4.getPath());
assertEquals("GET", handlerInfo4.getHttpMethod());
assertNull(handlerInfo4.getContentType());
assertEquals("APPLICATION_JSON", handlerInfo4.getAcceptType());
assertEquals("org.test.QuoteHandler", handlerInfo4.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> fetchQuotes(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo4.getHandlerMethod());
}
@@ -105,18 +117,27 @@ public class WebFluxMappingSymbolProviderTest {
List<? extends Object> addons = getAdditionalInformation(docUri);
assertEquals(3, addons.size());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "@/person/{id} -- GET").get(0);
assertEquals("@/person/{id} -- GET", handlerInfo1.getSymbol());
WebfluxHandlerInformation handlerInfo1 = getWebfluxHandler(addons, "/person/{id}", "GET").get(0);
assertEquals("/person/{id}", handlerInfo1.getPath());
assertEquals("GET", handlerInfo1.getHttpMethod());
assertNull(handlerInfo1.getContentType());
assertEquals("APPLICATION_JSON", handlerInfo1.getAcceptType());
assertEquals("org.test.PersonHandler", handlerInfo1.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> getPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo1.getHandlerMethod());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "@/person/ -- POST").get(0);
assertEquals("@/person/ -- POST", handlerInfo2.getSymbol());
WebfluxHandlerInformation handlerInfo2 = getWebfluxHandler(addons, "/person/", "POST").get(0);
assertEquals("/person/", handlerInfo2.getPath());
assertEquals("POST", handlerInfo2.getHttpMethod());
assertEquals("APPLICATION_JSON", handlerInfo2.getContentType());
assertNull(handlerInfo2.getAcceptType());
assertEquals("org.test.PersonHandler", handlerInfo2.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> createPerson(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo2.getHandlerMethod());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "@/person -- GET").get(0);
assertEquals("@/person -- GET", handlerInfo3.getSymbol());
WebfluxHandlerInformation handlerInfo3 = getWebfluxHandler(addons, "/person", "GET").get(0);
assertEquals("/person", handlerInfo3.getPath());
assertEquals("GET", handlerInfo3.getHttpMethod());
assertNull(handlerInfo3.getContentType());
assertEquals("APPLICATION_JSON", handlerInfo3.getAcceptType());
assertEquals("org.test.PersonHandler", handlerInfo3.getHandlerClass());
assertEquals("public Mono<org.springframework.web.reactive.function.server.ServerResponse> listPeople(org.springframework.web.reactive.function.server.ServerRequest)", handlerInfo3.getHandlerMethod());
}
@@ -146,11 +167,11 @@ public class WebFluxMappingSymbolProviderTest {
return harness.getServerWrapper().getComponents().getSpringIndexer().getAdditonalInformation(docUri);
}
private List<WebfluxHandlerInformation> getWebfluxHandler(List<? extends Object> addons, String symbol) {
private List<WebfluxHandlerInformation> getWebfluxHandler(List<? extends Object> addons, String path, String httpMethod) {
return addons.stream()
.filter((obj) -> obj instanceof WebfluxHandlerInformation)
.map((obj -> (WebfluxHandlerInformation) obj))
.filter((addon) -> addon.getSymbol().equals(symbol))
.filter((addon) -> addon.getPath().equals(path) && addon.getHttpMethod().equals(httpMethod))
.collect(Collectors.toList());
}

View File

@@ -11,7 +11,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M1</version>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
@@ -35,10 +35,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
</dependencies>
<build>
@@ -50,42 +46,4 @@
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

View File

@@ -0,0 +1,34 @@
package org.test;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
@Configuration
public class RouterExperiments {
@Bean
public RouterFunction<ServerResponse> superRoutingFunction() {
PersonHandler handler = new PersonHandler();
return nest(path("/super"),
nest(path("/something"),
nest(accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getPerson)
.andRoute(method(HttpMethod.GET), handler::listPeople)
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson)));
}
}

View File

@@ -1,72 +0,0 @@
package org.test;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class TradingUser {
@Id
private String id;
private String userName;
private String fullName;
public TradingUser() {
}
public TradingUser(String id, String userName, String fullName) {
this.id = id;
this.userName = userName;
this.fullName = fullName;
}
public TradingUser(String userName, String fullName) {
this.userName = userName;
this.fullName = fullName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TradingUser that = (TradingUser) o;
if (!id.equals(that.id)) return false;
return userName.equals(that.userName);
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + userName.hashCode();
return result;
}
}

View File

@@ -1,11 +0,0 @@
package org.test;
import reactor.core.publisher.Mono;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
public interface TradingUserRepository extends ReactiveMongoRepository<TradingUser, String> {
Mono<TradingUser> findByUserName(String userName);
}

View File

@@ -1,30 +1,24 @@
package org.test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
public class UserController {
private final TradingUserRepository tradingUserRepository;
public UserController(TradingUserRepository tradingUserRepository) {
this.tradingUserRepository = tradingUserRepository;
}
@GetMapping(path = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<TradingUser> listUsers() {
return this.tradingUserRepository.findAll();
public Flux<Object> listUsers() {
return null;
}
@GetMapping(path = "/users/{username}", produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<TradingUser> showUsers(@PathVariable String username) {
return this.tradingUserRepository.findByUserName(username);
public Mono<Object> showUsers(@PathVariable String username) {
return null;
}
}