Merge branch 'master' of github.com:spring-projects/sts4
This commit is contained in:
@@ -11,8 +11,7 @@
|
||||
openFile</programArgs>
|
||||
<vmArgs>-Dosgi.requiredJavaVersion=1.8
|
||||
--add-modules=ALL-SYSTEM
|
||||
-Xms40m
|
||||
-Xverify:none</vmArgs>
|
||||
-Xms40m</vmArgs>
|
||||
<vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts -Xdock:icon=../Resources/sts4.icns
|
||||
<argsX86_64>-Xmx1200m</argsX86_64>
|
||||
</vmArgsMac>
|
||||
@@ -67,6 +66,7 @@ openFile</programArgs>
|
||||
<feature id="org.eclipse.wst.jsdt.chromium.debug.feature" installMode="root"/>
|
||||
<feature id="org.eclipse.tm.terminal.feature" installMode="root"/>
|
||||
<feature id="org.eclipse.rse" installMode="root"/>
|
||||
<feature id="org.eclipse.epp.mpc" installMode="root"/>
|
||||
|
||||
<feature id="org.sonatype.m2e.buildhelper.feature" installMode="root"/>
|
||||
<feature id="org.sonatype.m2e.mavenarchiver.feature" installMode="root"/>
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
openFile</programArgs>
|
||||
<vmArgs>-Dosgi.requiredJavaVersion=1.8
|
||||
--add-modules=ALL-SYSTEM
|
||||
-Xms40m
|
||||
-Xverify:none</vmArgs>
|
||||
-Xms40m</vmArgs>
|
||||
<vmArgsMac>-XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts -Xdock:icon=../Resources/sts4.icns
|
||||
<argsX86_64>-Xmx1200m</argsX86_64>
|
||||
</vmArgsMac>
|
||||
@@ -67,6 +66,7 @@ openFile</programArgs>
|
||||
<feature id="org.eclipse.wst.jsdt.chromium.debug.feature" installMode="root"/>
|
||||
<feature id="org.eclipse.tm.terminal.feature" installMode="root"/>
|
||||
<feature id="org.eclipse.rse" installMode="root"/>
|
||||
<feature id="org.eclipse.epp.mpc" installMode="root"/>
|
||||
|
||||
<feature id="org.sonatype.m2e.buildhelper.feature" installMode="root"/>
|
||||
<feature id="org.sonatype.m2e.mavenarchiver.feature" installMode="root"/>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
contentType="org.eclipse.jdt.core.javaSource"
|
||||
id="org.eclipse.languageserver.languages.springboot">
|
||||
</contentTypeMapping>
|
||||
<contentTypeMapping
|
||||
<!-- <contentTypeMapping
|
||||
contentType="org.springframework.boot.ide.properties.application.properties"
|
||||
id="org.eclipse.languageserver.languages.springboot"
|
||||
languageId="spring-boot-properties">
|
||||
@@ -23,9 +23,9 @@
|
||||
contentType="org.springframework.boot.ide.properties.application.yml"
|
||||
id="org.eclipse.languageserver.languages.springboot"
|
||||
languageId="spring-boot-properties-yaml">
|
||||
</contentTypeMapping>
|
||||
</contentTypeMapping> -->
|
||||
</extension>
|
||||
|
||||
<!--
|
||||
<extension
|
||||
point="org.eclipse.core.contenttype.contentTypes">
|
||||
<content-type
|
||||
@@ -53,7 +53,7 @@
|
||||
file-names="application.yml,bootstrap.yml,application-dev.yml">
|
||||
</file-association>
|
||||
</extension>
|
||||
|
||||
-->
|
||||
<extension
|
||||
id="springbootjava-completion-computer"
|
||||
point="org.eclipse.jdt.ui.javaCompletionProposalComputer">
|
||||
@@ -99,7 +99,7 @@
|
||||
class="org.springframework.tooling.boot.ls.PrefsInitializer">
|
||||
</initializer>
|
||||
</extension>
|
||||
|
||||
<!--
|
||||
<extension
|
||||
point="org.eclipse.ui.editors">
|
||||
<editorContentTypeBinding
|
||||
@@ -143,6 +143,6 @@
|
||||
scopeName="source.yaml">
|
||||
</scopeNameContentTypeBinding>
|
||||
</extension>
|
||||
|
||||
-->
|
||||
|
||||
</plugin>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<content-type
|
||||
default-charset="UTF-8"
|
||||
id="org.springframework.tooling.concourse.pipeline"
|
||||
name="Cloudfoundry Pipeline"
|
||||
name="Concourse Pipeline Definition"
|
||||
priority="high">
|
||||
</content-type>
|
||||
<file-association
|
||||
@@ -21,7 +21,7 @@
|
||||
<content-type
|
||||
default-charset="UTF-8"
|
||||
id="org.springframework.tooling.concourse.task"
|
||||
name="Cloudfoundry Pipeline"
|
||||
name="Concourse Task Definition"
|
||||
priority="high">
|
||||
</content-type>
|
||||
<file-association
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.springframework.ide.vscode.boot.java.livehover.ComponentInjectionsHov
|
||||
import org.springframework.ide.vscode.boot.java.requestmapping.LiveAppURLSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingHoverProvider;
|
||||
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.requestmapping.WebfluxRouterSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.scope.ScopeCompletionProcessor;
|
||||
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippet;
|
||||
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippetContext;
|
||||
@@ -281,6 +282,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
|
||||
providers.put(Annotations.COMPONENT, new ComponentSymbolProvider());
|
||||
|
||||
providers.put(Annotations.REPOSITORY, new DataRepositorySymbolProvider());
|
||||
providers.put("", new WebfluxRouterSymbolProvider());
|
||||
|
||||
return new SpringIndexer(server, params, providers);
|
||||
}
|
||||
|
||||
@@ -165,5 +165,9 @@ public class BeansSymbolProvider implements SymbolProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.stream.Collectors;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
@@ -116,4 +117,9 @@ public class ComponentSymbolProvider implements SymbolProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Collection;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
@@ -139,4 +140,9 @@ public class DataRepositorySymbolProvider implements SymbolProvider {
|
||||
}
|
||||
return beanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Collection;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -26,5 +27,6 @@ public interface SymbolProvider {
|
||||
|
||||
Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding typeBinding, Collection<ITypeBinding> metaAnnotations, TextDocument doc);
|
||||
Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc);
|
||||
Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc);
|
||||
|
||||
}
|
||||
|
||||
@@ -181,4 +181,9 @@ public class RequestMappingSymbolProvider implements SymbolProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*******************************************************************************
|
||||
* 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 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
|
||||
*/
|
||||
public class WebfluxMethodFinder extends ASTVisitor {
|
||||
|
||||
private String method;
|
||||
private ASTNode root;
|
||||
|
||||
public WebfluxMethodFinder(ASTNode root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@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_HTTPMETHOD_METHODS.contains(name)) {
|
||||
method = name;
|
||||
}
|
||||
else if (name != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(name)) {
|
||||
method = extractMethodValue(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) {
|
||||
visitChildren = false;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*******************************************************************************
|
||||
* 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 WebfluxPathFinder extends ASTVisitor {
|
||||
|
||||
private String path;
|
||||
private ASTNode root;
|
||||
|
||||
public WebfluxPathFinder(ASTNode root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@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_ALL_PATH_METHODS.contains(name)) {
|
||||
path = WebfluxUtils.extractPath(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) {
|
||||
visitChildren = false;
|
||||
}
|
||||
|
||||
}
|
||||
return visitChildren;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*******************************************************************************
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.Block;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation;
|
||||
import org.eclipse.jdt.core.dom.Type;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.SymbolKind;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class WebfluxRouterSymbolProvider implements SymbolProvider {
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(Annotation node, ITypeBinding typeBinding,
|
||||
Collection<ITypeBinding> metaAnnotations, TextDocument doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SymbolInformation> getSymbols(MethodDeclaration methodDeclaration, TextDocument doc) {
|
||||
Type returnType = methodDeclaration.getReturnType2();
|
||||
if (returnType != null) {
|
||||
ITypeBinding resolvedBinding = returnType.resolveBinding();
|
||||
if (resolvedBinding != null) {
|
||||
if (WebfluxUtils.ROUTER_FUNCTION_TYPE.equals(resolvedBinding.getBinaryName())) {
|
||||
return getSymbolsForRouterFunction(methodDeclaration, doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<SymbolInformation> getSymbolsForRouterFunction(MethodDeclaration methodDeclaration,
|
||||
TextDocument doc) {
|
||||
List<SymbolInformation> result = new ArrayList<>();
|
||||
|
||||
Block body = methodDeclaration.getBody();
|
||||
body.accept(new ASTVisitor() {
|
||||
|
||||
@Override
|
||||
public boolean visit(MethodInvocation node) {
|
||||
IMethodBinding methodBinding = node.resolveMethodBinding();
|
||||
|
||||
if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) {
|
||||
extractMappingSymbol(node, doc, result);
|
||||
}
|
||||
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, List<SymbolInformation> result) {
|
||||
String foundPath = extractPathFromRouterFunction(node);
|
||||
String path = extractPath(node, foundPath);
|
||||
String httpMethod = extractMethod(node);
|
||||
|
||||
int methodNameStart = node.getName().getStartPosition();
|
||||
int invocationStart = node.getStartPosition();
|
||||
|
||||
if (path != null && path.length() > 0) {
|
||||
try {
|
||||
Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart)));
|
||||
String label = "@" + (path.startsWith("/") ? path : ("/" + path)) + (httpMethod == null || httpMethod.isEmpty() ? "" : " -- " + httpMethod);
|
||||
result.add(new SymbolInformation(label, SymbolKind.Interface, location));
|
||||
} catch (BadLocationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String extractPathFromRouterFunction(MethodInvocation routerInvocation) {
|
||||
WebfluxPathFinder pathFinder = new WebfluxPathFinder(routerInvocation);
|
||||
routerInvocation.accept(pathFinder);
|
||||
|
||||
String path = pathFinder.getPath();
|
||||
if (path == null) path = "";
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private String extractPath(ASTNode node, String path) {
|
||||
if (node == null || node instanceof TypeDeclaration) {
|
||||
return path;
|
||||
}
|
||||
|
||||
if (node instanceof MethodInvocation) {
|
||||
MethodInvocation methodInvocation = (MethodInvocation) node;
|
||||
IMethodBinding methodBinding = methodInvocation.resolveMethodBinding();
|
||||
|
||||
if (WebfluxUtils.ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
|
||||
String name = methodBinding.getName();
|
||||
if ("nest".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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return extractPath(node.getParent(), path);
|
||||
}
|
||||
|
||||
private String extractMethod(MethodInvocation routerInvocation) {
|
||||
WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation);
|
||||
routerInvocation.accept(methodFinder);
|
||||
|
||||
String method = methodFinder.getMethod();
|
||||
return method;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*******************************************************************************
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class WebfluxUtils {
|
||||
|
||||
public static final String ROUTER_FUNCTION_TYPE = "org.springframework.web.reactive.function.server.RouterFunction";
|
||||
public static final String ROUTER_FUNCTIONS_TYPE = "org.springframework.web.reactive.function.server.RouterFunctions";
|
||||
public static final String REQUEST_PREDICATES_TYPE = "org.springframework.web.reactive.function.server.RequestPredicates";
|
||||
|
||||
public static final String REQUEST_PREDICATE_PATH_METHOD = "path";
|
||||
public static final String REQUEST_PREDICATE_METHOD_METHOD = "method";
|
||||
|
||||
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) {
|
||||
List<?> arguments = node.arguments();
|
||||
if (arguments != null && arguments.size() > 0) {
|
||||
Object object = arguments.get(0);
|
||||
if (object instanceof StringLiteral) {
|
||||
String path = ((StringLiteral) object).getLiteralValue();
|
||||
return path;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isRouteMethodInvocation(IMethodBinding methodBinding) {
|
||||
if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
|
||||
String name = methodBinding.getName();
|
||||
if ("route".equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (ROUTER_FUNCTION_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) {
|
||||
String name = methodBinding.getName();
|
||||
if ("andRoute".equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.FileASTRequestor;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MarkerAnnotation;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
@@ -347,6 +348,7 @@ public class SpringIndexer {
|
||||
parser.setStatementsRecovery(true);
|
||||
parser.setBindingsRecovery(true);
|
||||
parser.setResolveBindings(true);
|
||||
parser.setIgnoreMethodBodies(false);
|
||||
|
||||
String[] sourceEntries = new String[] {};
|
||||
parser.setEnvironment(classpathEntries, sourceEntries, null, true);
|
||||
@@ -377,7 +379,7 @@ public class SpringIndexer {
|
||||
parser.setStatementsRecovery(true);
|
||||
parser.setBindingsRecovery(true);
|
||||
parser.setResolveBindings(true);
|
||||
parser.setIgnoreMethodBodies(true);
|
||||
parser.setIgnoreMethodBodies(false);
|
||||
|
||||
String[] sourceEntries = new String[] {};
|
||||
parser.setEnvironment(classpathEntries, sourceEntries, null, true);
|
||||
@@ -408,6 +410,17 @@ public class SpringIndexer {
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MethodDeclaration node) {
|
||||
try {
|
||||
extractSymbolInformation(node, docURI, docRef, content);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node) {
|
||||
try {
|
||||
@@ -462,6 +475,22 @@ public class SpringIndexer {
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbolInformation(MethodDeclaration methodDeclaration, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
Collection<SymbolProvider> providers = symbolProviders.getAll();
|
||||
if (!providers.isEmpty()) {
|
||||
TextDocument doc = getTempTextDocument(docURI, docRef, content);
|
||||
for (SymbolProvider provider : providers) {
|
||||
Collection<SymbolInformation> sbls = provider.getSymbols(methodDeclaration, doc);
|
||||
if (sbls != null) {
|
||||
sbls.forEach(symbol -> {
|
||||
symbols.add(symbol);
|
||||
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(symbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbolInformation(Annotation node, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
ITypeBinding typeBinding = node.resolveTypeBinding();
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*******************************************************************************
|
||||
* 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.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.project.harness.BootJavaLanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class WebFluxMappingSymbolProviderTest {
|
||||
|
||||
private BootJavaLanguageServerHarness harness;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
harness = BootJavaLanguageServerHarness.builder().build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRequestMappingSymbol() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()));
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI());
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoutesMappingSymbols() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()));
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI());
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/QuoteRouter.java").toUri().toString();
|
||||
List<? extends SymbolInformation> symbols = getSymbols(docUri);
|
||||
assertEquals(6, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@/hello -- GET", docUri, 22, 5, 22, 70));
|
||||
assertTrue(containsSymbol(symbols, "@/echo -- POST", docUri, 23, 5, 23, 101));
|
||||
assertTrue(containsSymbol(symbols, "@/quotes -- GET", docUri, 24, 5, 24, 86));
|
||||
assertTrue(containsSymbol(symbols, "@/quotes -- GET", docUri, 25, 5, 25, 94));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedRoutesMappingSymbols() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI()));
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-webflux-project/").toURI());
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/NestedRouter.java").toUri().toString();
|
||||
List<? extends SymbolInformation> symbols = getSymbols(docUri);
|
||||
assertEquals(5, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@/person/{id} -- GET", docUri, 27, 6, 27, 45));
|
||||
assertTrue(containsSymbol(symbols, "@/person/ -- POST", docUri, 29, 6, 29, 83));
|
||||
assertTrue(containsSymbol(symbols, "@/person -- GET", docUri, 28, 7, 28, 60));
|
||||
}
|
||||
|
||||
private boolean containsSymbol(List<? extends SymbolInformation> symbols, String name, String uri, int startLine, int startCHaracter, int endLine, int endCharacter) {
|
||||
for (Iterator<? extends SymbolInformation> iterator = symbols.iterator(); iterator.hasNext();) {
|
||||
SymbolInformation symbol = iterator.next();
|
||||
|
||||
if (symbol.getName().equals(name)
|
||||
&& symbol.getLocation().getUri().equals(uri)
|
||||
&& symbol.getLocation().getRange().getStart().getLine() == startLine
|
||||
&& symbol.getLocation().getRange().getStart().getCharacter() == startCHaracter
|
||||
&& symbol.getLocation().getRange().getEnd().getLine() == endLine
|
||||
&& symbol.getLocation().getRange().getEnd().getCharacter() == endCharacter) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<? extends SymbolInformation> getSymbols(String docUri) {
|
||||
return harness.getServerWrapper().getComponents().getSpringIndexer().getSymbols(docUri);
|
||||
}
|
||||
}
|
||||
233
headless-services/commons/commons-boot/src/test/resources/test-projects/test-webflux-project/mvnw
vendored
Executable file
233
headless-services/commons/commons-boot/src/test/resources/test-projects/test-webflux-project/mvnw
vendored
Executable file
@@ -0,0 +1,233 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven2 Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
#
|
||||
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
|
||||
# for the new JDKs provided by Oracle.
|
||||
#
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
|
||||
#
|
||||
# Oracle JDKs
|
||||
#
|
||||
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
|
||||
#
|
||||
# Apple JDKs
|
||||
#
|
||||
export JAVA_HOME=`/usr/libexec/java_home`
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Migwn, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
# TODO classpath?
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
local basedir=$(pwd)
|
||||
local wdir=$(pwd)
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
wdir=$(cd "$wdir/.."; pwd)
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} "$@"
|
||||
@@ -0,0 +1,145 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven2 Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
|
||||
set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>test-webflux-project</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.M1</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</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>
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.test;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Application.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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 NestedRouter {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> routingFunction() {
|
||||
PersonHandler handler = new PersonHandler();
|
||||
|
||||
return nest(path("/person"),
|
||||
nest(accept(APPLICATION_JSON),
|
||||
route(GET("/{id}"), handler::getPerson)
|
||||
.andRoute(method(HttpMethod.GET), handler::listPeople)
|
||||
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.test;
|
||||
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class PersonHandler {
|
||||
|
||||
public Mono<ServerResponse> getPerson(ServerRequest request) {
|
||||
return ServerResponse.notFound().build();
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> createPerson(ServerRequest request) {
|
||||
return ServerResponse.notFound().build();
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> listPeople(ServerRequest request) {
|
||||
return ServerResponse.notFound().build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.time.Instant;
|
||||
|
||||
public class Quote {
|
||||
|
||||
private static final MathContext MATH_CONTEXT = new MathContext(2);
|
||||
|
||||
private String ticker;
|
||||
|
||||
private BigDecimal price;
|
||||
|
||||
private Instant instant;
|
||||
|
||||
public Quote() {
|
||||
}
|
||||
|
||||
public Quote(String ticker, BigDecimal price) {
|
||||
this.ticker = ticker;
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Quote(String ticker, Double price) {
|
||||
this(ticker, new BigDecimal(price, MATH_CONTEXT));
|
||||
}
|
||||
|
||||
public String getTicker() {
|
||||
return ticker;
|
||||
}
|
||||
|
||||
public void setTicker(String ticker) {
|
||||
this.ticker = ticker;
|
||||
}
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(BigDecimal price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Instant getInstant() {
|
||||
return instant;
|
||||
}
|
||||
|
||||
public void setInstant(Instant instant) {
|
||||
this.instant = instant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Quote{" +
|
||||
"ticker='" + ticker + '\'' +
|
||||
", price=" + price +
|
||||
", instant=" + instant +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.SynchronousSink;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class QuoteGenerator {
|
||||
|
||||
private final MathContext mathContext = new MathContext(2);
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
private final List<Quote> prices = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Bootstraps the generator with tickers and initial prices
|
||||
*/
|
||||
public QuoteGenerator() {
|
||||
this.prices.add(new Quote("CTXS", 82.26));
|
||||
this.prices.add(new Quote("DELL", 63.74));
|
||||
this.prices.add(new Quote("GOOG", 847.24));
|
||||
this.prices.add(new Quote("MSFT", 65.11));
|
||||
this.prices.add(new Quote("ORCL", 45.71));
|
||||
this.prices.add(new Quote("RHT", 84.29));
|
||||
this.prices.add(new Quote("VMW", 92.21));
|
||||
}
|
||||
|
||||
|
||||
public Flux<Quote> fetchQuoteStream(Duration period) {
|
||||
|
||||
// We use here Flux.generate to create quotes,
|
||||
// iterating on each stock starting at index 0
|
||||
return Flux.generate(() -> 0,
|
||||
(BiFunction<Integer, SynchronousSink<Quote>, Integer>) (index, sink) -> {
|
||||
Quote updatedQuote = updateQuote(this.prices.get(index));
|
||||
sink.next(updatedQuote);
|
||||
return ++index % this.prices.size();
|
||||
})
|
||||
// We want to emit them with a specific period;
|
||||
// to do so, we zip that Flux with a Flux.interval
|
||||
.zipWith(Flux.interval(period)).map(t -> t.getT1())
|
||||
// Because values are generated in batches,
|
||||
// we need to set their timestamp after their creation
|
||||
.map(quote -> {
|
||||
quote.setInstant(Instant.now());
|
||||
return quote;
|
||||
})
|
||||
.log("io.spring.workshop.stockquotes");
|
||||
}
|
||||
|
||||
private Quote updateQuote(Quote quote) {
|
||||
BigDecimal priceChange = quote.getPrice()
|
||||
.multiply(new BigDecimal(0.05 * this.random.nextDouble()), this.mathContext);
|
||||
return new Quote(quote.getTicker(), quote.getPrice().add(priceChange));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.test;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import static java.time.Duration.ofMillis;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON;
|
||||
import static org.springframework.http.MediaType.APPLICATION_STREAM_JSON;
|
||||
import static org.springframework.http.MediaType.TEXT_PLAIN;
|
||||
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
|
||||
|
||||
@Component
|
||||
public class QuoteHandler {
|
||||
|
||||
private final Flux<Quote> quoteStream;
|
||||
|
||||
public QuoteHandler(QuoteGenerator quoteGenerator) {
|
||||
this.quoteStream = quoteGenerator.fetchQuoteStream(ofMillis(200)).share();
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> hello(ServerRequest request) {
|
||||
return ok().contentType(TEXT_PLAIN)
|
||||
.body(BodyInserters.fromObject("Hello Spring!"));
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> echo(ServerRequest request) {
|
||||
return ok().contentType(TEXT_PLAIN)
|
||||
.body(request.bodyToMono(String.class), String.class);
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> streamQuotes(ServerRequest request) {
|
||||
return ok()
|
||||
.contentType(APPLICATION_STREAM_JSON)
|
||||
.body(this.quoteStream, Quote.class);
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> fetchQuotes(ServerRequest request) {
|
||||
int size = Integer.parseInt(request.queryParam("size").orElse("10"));
|
||||
return ok()
|
||||
.contentType(APPLICATION_JSON)
|
||||
.body(this.quoteStream.take(size), Quote.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.test;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON;
|
||||
import static org.springframework.http.MediaType.APPLICATION_STREAM_JSON;
|
||||
import static org.springframework.http.MediaType.TEXT_PLAIN;
|
||||
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;
|
||||
|
||||
@Configuration
|
||||
public class QuoteRouter {
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> route(QuoteHandler quoteHandler) {
|
||||
return RouterFunctions
|
||||
.route(GET("/hello").and(accept(TEXT_PLAIN)), quoteHandler::hello)
|
||||
.andRoute(POST("/echo").and(accept(TEXT_PLAIN).and(contentType(TEXT_PLAIN))), quoteHandler::echo)
|
||||
.andRoute(GET("/quotes").and(accept(APPLICATION_JSON)), quoteHandler::fetchQuotes)
|
||||
.andRoute(GET("/quotes").and(accept(APPLICATION_STREAM_JSON)), quoteHandler::streamQuotes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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;
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
@GetMapping(path = "/users/{username}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Mono<TradingUser> showUsers(@PathVariable String username) {
|
||||
return this.tradingUserRepository.findByUserName(username);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -99,8 +99,8 @@
|
||||
"vsce-package": "vsce package"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageclient": "^3.4.2",
|
||||
"commons-vscode": "0.1.4"
|
||||
"commons-vscode": "file:../commons-vscode/commons-vscode-0.1.4.tgz",
|
||||
"vscode-languageclient": "^3.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vsce": "^1.36.1",
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
"vsce-package": "vsce package"
|
||||
},
|
||||
"dependencies": {
|
||||
"commons-vscode": "0.1.4",
|
||||
"commons-vscode": "file:../commons-vscode/commons-vscode-0.1.4.tgz",
|
||||
"vscode-languageclient": "^3.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -58,8 +58,8 @@
|
||||
"vsce-package": "vsce package"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageclient": "^3.4.2",
|
||||
"commons-vscode": "0.1.4"
|
||||
"commons-vscode": "file:../commons-vscode/commons-vscode-0.1.4.tgz",
|
||||
"vscode-languageclient": "^3.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vsce": "^1.36.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vscode-spring-boot",
|
||||
"displayName": "Spring Boot Support",
|
||||
"displayName": "Spring Boot Tools",
|
||||
"description": "Provides validation and content assist for Spring Boot `application.properties`, `application.yml` properties files. As well as Boot-specific support for `.java` files.",
|
||||
"icon": "spring-boot-logo.png",
|
||||
"version": "0.1.5",
|
||||
|
||||
Reference in New Issue
Block a user