Skip to content

Commit

Permalink
Refactorings while fixing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cromoteca committed Aug 6, 2024
1 parent 8403ed1 commit fc64cb9
Show file tree
Hide file tree
Showing 98 changed files with 290 additions and 353 deletions.
7 changes: 5 additions & 2 deletions packages/java/annotations/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
</dependencies>
</project>
6 changes: 6 additions & 0 deletions packages/java/annotations/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module com.vaadin.hilla.annotations {
requires spring.context;
requires reactor.core;

exports com.vaadin.hilla;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.vaadin.hilla.engine;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import com.vaadin.flow.server.ExecutionFailedException;
import com.vaadin.flow.server.frontend.FrontendUtils;

public class EngineConfiguration {
Expand All @@ -25,6 +29,7 @@ public class EngineConfiguration {
private GeneratorConfiguration generator;
private Path outputDir;
private ParserConfiguration parser;
private EndpointProvider offlineEndpointProvider;

public EngineConfiguration() {
baseDir = Path.of(System.getProperty("user.dir"));
Expand Down Expand Up @@ -134,4 +139,28 @@ public Path getOpenAPIFile(boolean isProductionMode) {
return isProductionMode ? classesDir.resolve(OPEN_API_PATH)
: buildDir.resolve(OPEN_API_PATH);
}

public EndpointProvider getOfflineEndpointProvider() {
if (offlineEndpointProvider != null) {
return offlineEndpointProvider;
}

return () -> {
try {
return new AotEndpointFinder(this).findEndpointClasses();
} catch (IOException | InterruptedException e) {
throw new ExecutionFailedException(e);
}
};
}

public void setOfflineEndpointProvider(
EndpointProvider offlineEndpointProvider) {
this.offlineEndpointProvider = offlineEndpointProvider;
}

@FunctionalInterface
public interface EndpointProvider {
List<Class<?>> findEndpoints() throws ExecutionFailedException;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.vaadin.hilla.internal;

import com.vaadin.hilla.engine.EngineConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -28,6 +29,8 @@

import com.vaadin.hilla.engine.ParserProcessor;

import java.nio.file.Path;

/**
* An implementation of the EndpointGeneratorTaskFactory, which creates endpoint
* generator tasks.
Expand All @@ -52,6 +55,7 @@ private static FrontendTools buildTools(Options options) {

@Override
public TaskGenerateEndpoint createTaskGenerateEndpoint(Options options) {
configureFromOptions(options);
if (!options.isRunNpmInstall() && !options.isDevBundleBuild()
&& !options.isProductionMode()) {
// Skip for prepare-frontend phase and in production server
Expand All @@ -69,6 +73,7 @@ public TaskGenerateEndpoint createTaskGenerateEndpoint(Options options) {

@Override
public TaskGenerateOpenAPI createTaskGenerateOpenAPI(Options options) {
configureFromOptions(options);
if (!options.isRunNpmInstall() && !options.isDevBundleBuild()
&& !options.isProductionMode()) {
// Skip for prepare-frontend phase and in production server
Expand Down Expand Up @@ -98,4 +103,13 @@ public void execute() {
LOGGER.debug("Skipping generating OpenAPI spec");
}
}

private static void configureFromOptions(Options options) {
var conf = EngineConfiguration.getDefault();
Path buildDir = options.getBuildDirectory().toPath();
conf.setBaseDir(options.getNpmFolder().toPath());
conf.setBuildDir(buildDir);
conf.setClassesDir(buildDir.resolve("classes"));
conf.setOutputDir(options.getFrontendGeneratedFolder().toPath());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,30 +88,25 @@ public class TaskGenerateOpenAPIImpl extends AbstractTaskEndpointGenerator
*/
@Override
public void execute() throws ExecutionFailedException {
try {
var engineConfiguration = EngineConfiguration.getDefault();
if (isProductionMode) {
var endpoints = new AotEndpointFinder(engineConfiguration)
.findEndpointClasses();
var engineConfiguration = EngineConfiguration.getDefault();
if (isProductionMode) {
var endpoints = engineConfiguration.getOfflineEndpointProvider()
.findEndpoints();
var processor = new ParserProcessor(engineConfiguration,
classLoader, true);
processor.process(endpoints);
} else {
ApplicationContextProvider.runOnContext(applicationContext -> {
List<Class<?>> endpoints = engineConfiguration.getParser()
.getEndpointAnnotations().stream()
.map(applicationContext::getBeansWithAnnotation)
.map(Map::values).flatMap(Collection::stream)
.map(Object::getClass).distinct()
.collect(Collectors.toList());
var processor = new ParserProcessor(engineConfiguration,
classLoader, true);
classLoader, false);
processor.process(endpoints);
} else {
ApplicationContextProvider.runOnContext(applicationContext -> {
List<Class<?>> endpoints = engineConfiguration.getParser()
.getEndpointAnnotations().stream()
.map(applicationContext::getBeansWithAnnotation)
.map(Map::values).flatMap(Collection::stream)
.map(Object::getClass).distinct()
.collect(Collectors.toList());
var processor = new ParserProcessor(engineConfiguration,
classLoader, false);
processor.process(endpoints);
});
}

} catch (Exception e) {
throw new ExecutionFailedException(e);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

Expand Down Expand Up @@ -34,11 +35,39 @@ public class NodeTasksEndpointTest extends TaskTest {
public static class ConnectEndpointsForTesting {
}

public static class MyEndpoint {
@Endpoint
public class MyEndpoint {
public void foo(String bar) {
}

public String bar(String baz) {
return baz;
}
}

@Endpoint(value = "CustomEndpointName")
public class CustomEndpoint {
public void foo(String bar) {
}

public String bar(String baz) {
return baz;
}
}

@Endpoint("WithoutValueEqual")
public class EndpointNoValue {
public void foo(String bar) {
}

public String bar(String baz) {
return baz;
}
}

@BeforeEach
public void setUp() throws IOException {
public void setUp()
throws IOException, NoSuchFieldException, IllegalAccessException {
Lookup mockLookup = Mockito.mock(Lookup.class);
Mockito.doReturn(new EndpointGeneratorTaskFactoryImpl())
.when(mockLookup).lookup(EndpointGeneratorTaskFactory.class);
Expand All @@ -49,6 +78,18 @@ public void setUp() throws IOException {
EndpointController.class, ConnectEndpointsForTesting.class)))
.when(mockLookup).lookup(ClassFinder.class);

var mockApplicationContext = Mockito.mock(ApplicationContext.class);
Mockito.doReturn(Map.of("MyEndpoint", new MyEndpoint(),
"CustomEndpointName", CustomEndpoint.class, "WithoutValueEqual",
EndpointNoValue.class)).when(mockApplicationContext)
.getBeansWithAnnotation(Endpoint.class);
Mockito.doReturn(Map.of()).when(mockApplicationContext)
.getBeansWithAnnotation(BrowserCallable.class);
var applicationContextField = ApplicationContextProvider.class
.getDeclaredField("applicationContext");
applicationContextField.setAccessible(true);
applicationContextField.set(null, mockApplicationContext);

options = new Options(mockLookup, getTemporaryDirectory().toFile())
.withFrontendDirectory(getTemporaryDirectory()
.resolve(getFrontendDirectory()).toFile())
Expand Down Expand Up @@ -85,24 +126,16 @@ public void should_GenerateEndpointFilesInDevBuildTask() throws Exception {
public void should_GenerateEndpointFilesInProductionBuildTask()
throws Exception {
options = options.withProductionMode(true);
EngineConfiguration.getDefault()
.setOfflineEndpointProvider(() -> List.of(MyEndpoint.class));

new NodeTasks(options).execute();
EngineConfiguration.getDefault().setOfflineEndpointProvider(null);
assertEndpointFilesInProductionMode(true);
}

@Test
public void should_GenerateEndpointFilesInDevServerTask() throws Exception {
var mockApplicationContext = Mockito.mock(ApplicationContext.class);
Mockito.doReturn(Map.of("MyEndpoint", new MyEndpoint()))
.when(mockApplicationContext)
.getBeansWithAnnotation(Endpoint.class);
Mockito.doReturn(Map.of()).when(mockApplicationContext)
.getBeansWithAnnotation(BrowserCallable.class);
var applicationContextField = ApplicationContextProvider.class
.getDeclaredField("applicationContext");
applicationContextField.setAccessible(true);
applicationContextField.set(null, mockApplicationContext);

options = options.withRunNpmInstall(true);
new NodeTasks(options).execute();
assertEndpointFiles(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,12 @@ public void should_ThrowError_When_ClassPathIsNotSet() {
}

@Test
public void should_ThrowError_When_EndpointAnnotationNameIsNotSet() {
public void should_ThrowError_When_EndpointAnnotationsIsNotSet() {
var e = assertThrows(NullPointerException.class,
() -> new Parser().classLoader(getClass().getClassLoader())
.classPath(defaultClassPathElements)
.execute(List.of()));
assertEquals("[JVM Parser] endpointAnnotationName is not provided.",
assertEquals("[JVM Parser] endpointAnnotations is not provided.",
e.getMessage());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,22 @@ public class BasicTests {
private static final List<String> STEPS = new LinkedList<>();

static {
STEPS.add("-> Root(ScanResult)");
STEPS.add("-> Root(ScanResult)/Endpoint(BasicEndpoint)");
STEPS.add("-> Root(ScanResult)/Endpoint(BasicEndpoint)/Field(foo)");
STEPS.add("<- Root(ScanResult)/Endpoint(BasicEndpoint)/Field(foo)");
STEPS.add(
"-> Root(ScanResult)/Endpoint(BasicEndpoint)/Field(fieldFoo)");
STEPS.add(
"<- Root(ScanResult)/Endpoint(BasicEndpoint)/Field(fieldFoo)");
STEPS.add(
"-> Root(ScanResult)/Endpoint(BasicEndpoint)/Field(fieldBar)");
STEPS.add(
"<- Root(ScanResult)/Endpoint(BasicEndpoint)/Field(fieldBar)");
STEPS.add("<- Root(ScanResult)/Endpoint(BasicEndpoint)");
STEPS.add("-> Root(ScanResult)/Entity(Sample)");
STEPS.add("-> Root(ScanResult)/Entity(Sample)/Method(methodFoo)");
STEPS.add("<- Root(ScanResult)/Entity(Sample)/Method(methodFoo)");
STEPS.add("-> Root(ScanResult)/Entity(Sample)/Method(methodBar)");
STEPS.add("<- Root(ScanResult)/Entity(Sample)/Method(methodBar)");
STEPS.add("<- Root(ScanResult)/Entity(Sample)");
STEPS.add("<- Root(ScanResult)");
STEPS.add("-> Root(List)");
STEPS.add("-> Root(List)/Endpoint(BasicEndpoint)");
STEPS.add("-> Root(List)/Endpoint(BasicEndpoint)/Field(foo)");
STEPS.add("<- Root(List)/Endpoint(BasicEndpoint)/Field(foo)");
STEPS.add("-> Root(List)/Endpoint(BasicEndpoint)/Field(fieldFoo)");
STEPS.add("<- Root(List)/Endpoint(BasicEndpoint)/Field(fieldFoo)");
STEPS.add("-> Root(List)/Endpoint(BasicEndpoint)/Field(fieldBar)");
STEPS.add("<- Root(List)/Endpoint(BasicEndpoint)/Field(fieldBar)");
STEPS.add("<- Root(List)/Endpoint(BasicEndpoint)");
STEPS.add("-> Root(List)/Entity(Sample)");
STEPS.add("-> Root(List)/Entity(Sample)/Method(methodFoo)");
STEPS.add("<- Root(List)/Entity(Sample)/Method(methodFoo)");
STEPS.add("-> Root(List)/Entity(Sample)/Method(methodBar)");
STEPS.add("<- Root(List)/Entity(Sample)/Method(methodBar)");
STEPS.add("<- Root(List)/Entity(Sample)");
STEPS.add("<- Root(List)");
}

private final List<String> classPath;
Expand All @@ -55,17 +51,23 @@ public void should_TraverseInConsistentOrder() {
var openAPI = new Parser().classLoader(getClass().getClassLoader())
.classPath(classPath)
.endpointAnnotations(List.of(Endpoint.class))
.endpointExposedAnnotations(List.of(EndpointExposed.class))
.addPlugin(new BasicPlugin()).execute(endpoints);

// The list of endpoints seems to be serialized as "List12". The
// replacement tries to accommodate for similar representations.
assertEquals(String.join("\n", STEPS),
openAPI.getExtensions().get(BasicPlugin.FOOTSTEPS_STORAGE_KEY));
((String) openAPI.getExtensions()
.get(BasicPlugin.FOOTSTEPS_STORAGE_KEY))
.replaceAll("List\\w*", "List"));
}

@Test
public void should_UpdateNodesAndCollectNames() {
var openAPI = new Parser().classLoader(getClass().getClassLoader())
.classPath(classPath)
.endpointAnnotations(List.of(Endpoint.class))
.endpointExposedAnnotations(List.of(EndpointExposed.class))
.addPlugin(new BasicPlugin()).execute(endpoints);

assertEquals(String.join(", ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static void setUp() {
.classLoader(DependencyTests.class.getClassLoader())
.classPath(classPath)
.endpointAnnotations(List.of(Endpoint.class))
.endpointExposedAnnotations(List.of(EndpointExposed.class))
.addPlugin(new DependencyPlugin()).execute(endpoints);
}

Expand Down
5 changes: 5 additions & 0 deletions packages/java/parser-jvm-plugin-backbone/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>hilla-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>hilla-parser-jvm-utils</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.vaadin.hilla.parser.plugins.backbone;

import java.lang.annotation.Annotation;
import java.util.stream.Stream;

import jakarta.annotation.Nonnull;
Expand Down Expand Up @@ -92,11 +93,11 @@ public NodeDependencies scan(@Nonnull NodeDependencies nodeDependencies) {
*/
private Node<?, ?> createEndpointHierarchyClassNode(
ClassInfoModel classInfo) {
var endpointExposedAnnotationName = getStorage().getParserConfig()
var endpointExposedAnnotations = getStorage().getParserConfig()
.getEndpointExposedAnnotations();
var exposed = classInfo.getAnnotations().stream()
.map(AnnotationInfoModel::getName)
.anyMatch(endpointExposedAnnotationName::equals);
.map(annInfo -> ((Annotation) annInfo.get()).annotationType())
.anyMatch(endpointExposedAnnotations::contains);
var classInfoNode = exposed ? EndpointExposedNode.of(classInfo)
: EndpointNonExposedNode.of(classInfo);
return classInfoNode;
Expand Down
Loading

0 comments on commit fc64cb9

Please sign in to comment.