Giter Site home page Giter Site logo

spring-projects-experimental / spring-fu Goto Github PK

View Code? Open in Web Editor NEW
1.7K 1.7K 139.0 17.64 MB

Configuration DSLs for Spring Boot

License: Apache License 2.0

Kotlin 44.61% HTML 0.02% Shell 0.11% Java 55.26% Mustache 0.01%
coroutines graalvm kotlin spring spring-boot

spring-fu's People

Contributors

agebhar1 avatar alek-sys avatar alexczar avatar aneveu avatar davinkevin avatar eanekrasov avatar eddumelendez avatar fteychene avatar hamid646m avatar hauerio avatar irus avatar jnizet avatar kinmarui avatar ksvasan avatar linkedlist avatar lucapiccinelli avatar making avatar malltshik avatar miguelarca avatar neversleepz avatar pull-vert avatar sandjelkovic avatar sdeleuze avatar sendilkumarn avatar silasmahler avatar skivol avatar t-kameyama avatar tgirard12 avatar vpelikh avatar wpanas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spring-fu's Issues

Leverage Spring Boot starters

Spring Fu modules could leverage Spring Boot starters with a more fine grained logic. We should avoid dependency exclusion for most use case.

Improve documentation about modules

The documentation isn't very clear about what a module is, IMHO.

Maybe it's because nothing is published in any repository yet, but it would be helpful to specify that a module is just a Java library, that you just need to add to the compile dependencies (or maybe runtime for some of them) of the project, as you would do with a spring-boot starter, to have access to additional capabilities and additional DSL extensions.

An example gradle/Maven snippet showing how to add the module would help.

Reuse Spring Boot configuration classes in a functional way

If we're willing to interoperate w/ configuration annotations then we could change the default ApplicationContext instance to AnnotationConfigApplicationContext and hat would allow bean<FooConfig>() to work out of the box. but that would also require reflection and annotations and other things that frustrate tools like Graal.

If we don't want annotations then we could possibly register modules which then register beans which e arrive at by manually invoking methods in existing java config classes?

Or we could somehow automatically generate functional config from Java configuration classes.

Introduce a Spring Fu Gradle plugin

This plugin could provide the following functionalities with first-class Gradle Kotlin DSL support for configuration:

  • Preconfigure Junit 5 by applying val test by tasks.getting(Test::class) { useJUnitPlatform() } automatically
  • Apply dependency management
  • Provide shadow plugin like functionalities
  • Integrate JAR minimization mechanism + removal of annotation/XML stuff in Spring JARs as done is #34
  • Preconfigure Kotlin null-safety suppport, bytecode level, etc.

Serve static website

Hi,

I would like to know if Spring-fu is able to serve static websites.

Many thanks in advance.

Cheers

Juan Antonio

Graal native image support

Currently even with Graal snapshots it fails with following error:

mx native-image -Dio.netty.noUnsafe=true -H:ReflectionConfigurationFiles=/home/seb/workspace/spring-fu/samples/simple-webapp/graal.json -H:+ReportUnsupportedElementsAtRuntime -Dfile.encoding=UTF-8  -jar /home/seb/workspace/spring-fu/samples/simple-webapp/build/libs/simple-webapp-all.jar 
   classlist:  10,845.71 ms
       (cap):   3,785.48 ms
       setup:   7,078.43 ms
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Jun 05, 2018 2:48:49 PM io.netty.util.internal.PlatformDependent <clinit>
INFO: Your platform does not provide complete low-level API for accessing direct buffers reliably. Unless explicitly requested, heap buffer will always be preferred to avoid potential system instability.
    analysis:  38,365.98 ms
fatal error: java.lang.reflect.MalformedParameterizedTypeException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598)
	at java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1005)
	at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:381)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:281)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:378)
	at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:104)
Caused by: java.lang.reflect.MalformedParameterizedTypeException
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.validateConstructorArguments(ParameterizedTypeImpl.java:58)
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.<init>(ParameterizedTypeImpl.java:51)
	at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.make(ParameterizedTypeImpl.java:92)
	at sun.reflect.generics.factory.CoreReflectionFactory.makeParameterizedType(CoreReflectionFactory.java:105)
	at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:140)
	at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
	at sun.reflect.generics.repository.ClassRepository.getSuperInterfaces(ClassRepository.java:108)
	at java.lang.Class.getGenericInterfaces(Class.java:913)
	at com.oracle.svm.hosted.analysis.Inflation.fillGenericInfo(Inflation.java:240)
	at com.oracle.svm.hosted.analysis.Inflation.checkType(Inflation.java:148)
	at java.lang.Iterable.forEach(Iterable.java:75)
	at java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1080)
	at com.oracle.svm.hosted.analysis.Inflation.checkObjectGraph(Inflation.java:125)
	at com.oracle.graal.pointsto.BigBang.checkObjectGraph(BigBang.java:582)
	at com.oracle.graal.pointsto.BigBang.finish(BigBang.java:554)
	at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:642)
	at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$0(NativeImageGenerator.java:364)
	at java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Error: Image building with exit status 1

graal.json

[
  {
    "name" : "io.netty.channel.socket.nio.NioSocketChannel",
    "methods" : [
      { "name" : "<init>", "parameterTypes" : [] }
    ]
  },
  {
    "name" : "io.netty.channel.socket.nio.NioServerSocketChannel",
    "methods" : [
      { "name" : "<init>", "parameterTypes" : [] }
    ]
  }
]

We need to report this kind of issues to Graal project and provide custom spring-fu.json reflection configuration in order to provide first class support for native images.

Experiment about GSON + Actson as an alternative to Jackson

Jackson is powerful and provides non-blocking parsing support, but also consumes quite a lot of memory on startup. Heap memory after startup is 14 MB without it and 65 MB with (before GC).

Spring MVC has already GSON support but we can't use it since it does not provides non-blocking JSON streaming support.

Maybe we could combine GSON with actson for the non-blocking streaming part in order to build a more lightweight JSON WebFlux codec.

Explore JUnit 5 integration

Currently, Spring Fu applications are tested mainly in 2 ways:

  • Unit tests for individual classes is made easy by generalized constructor injection usage, potentially with Mocking, without ApplicationContext being involved (we need to add examples of that as part of #44).
  • Integration tests by just running the application, eventually with a specified profile like in this example.

Even if Spring Fu is designed to be testable with not specific support, we should explore if JUnit 5 integration makes sense.

@sbrannen Since Spring Fu is heavily based on ApplicationContextInitializer, is there something already supported in SpringExtension we could leverage to register beans on the context and take advantage of test classes @Autowired support for example?

Support multipart codecs

It will provide org.synchronoss.cloud:nio-multipart-parser dependency and the related functional configuration.

Spring classpath filtering via Gradle plugin

We should be able to do that with something like:

compile("org.springframework:spring-web") {
		registerTransform {
			from.attribute(filtered, false).attribute(artifactType, "jar")
			to.attribute(filtered, true).attribute(artifactType, "jar")
			artifactTransform(FilterClasses::class.java)
		}
	}
}

// Same for spring-webflux, spring-context, spring-data-commons, etc.
class SpringFuWebFilter : ArtifactTransform() {
	
	private val classesToFilter = arrayOf(
			"org/springframework/remoting/**",
			"org/springframework/web/accept/**",
			"org/springframework/web/bind/**",
			"org/springframework/web/client/**",
			"org/springframework/web/context/**",
			"org/springframework/web/filter/**",
			"org/springframework/web/jsf/**",
			"org/springframework/web/method/**",
			"org/springframework/web/multipart/**",
		)
)

	override fun transform(input: File): List<File> {
		return if (...) listOf(input) else emptyList()
	}
}

See also https://github.com/gradle/gradle/blob/master/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt

Add support for reusable conditions

Maybe something on Spring Framework side, or directly typealias Condition = (ApplicationContext) -> Boolean on Spring Fu side. Conditions should be reused in Spring Fu internals and available to the users as well.

Only the last WebFlux routes is available

Considering the following app :

application {
	webflux {
		server(netty()) {
			routes { GET("/route1", { ok().syncBody("route1") }) }
                        routes { GET("/route2", { ok().syncBody("route2") }) }
                }
	}
}

Only the last routes is available, depending of the order in the DSL.

Kotlin code formatting not in line with official Kotlin style guide

Hi, I've started looking at Spring-fu code, and immediately stumbled upon this. I commend the project developers on deciding to use tabs for indentation, but smart indent for arguments? Is this the recommended formatting for spring-fu? One of the benefits of using tab is customizable indent width without change in the source itself, smart-indent kills this benefit. Look at the part of spring-fu code on the screenshot
https://k62.kn3.net/B/E/A/3/4/7/558.png
2) is with indent settings in IntelliJ set to 4-4-8 (probably what spring-fu original devs have)

  1. is same code without any change with 2-2-4 setting in IntelliJ
  2. is proposed best practice, if written that way, code will look good regardless of settings.
    (sorry, I screwed up numbering while editing screenshot, that's why my comments are 2 -> 1 -> 3 ๐Ÿ˜„ )
    Also please note that 3) is recommended by official kotlin style guide: https://kotlinlang.org/docs/reference/coding-conventions.html#function-formatting
    Even though being fan of using tabs I ignore parts of the guide, mostly it is sound and logical, including parameters formatting recommendation mentioned above.
    I also see that there are unneeded double indents e.g.
application {
	logging {
		logback = logback {
			rollingFileAppender(
					file = File.createTempFile("mylog", ".txt"),
					name = "MY_ROLLING",
					pattern = "%d{yyyy-MM}",
					fileNamePattern = "%i.gz",
					maxFileSize = "2GB",
					maxHistory = 11,
					totalSizeCap = "1MB",
					append = false
			)
		}
	}
}

instead of

	logging {
		logback = logback {
			rollingFileAppender(
				file = File.createTempFile("mylog", ".txt"),
				name = "MY_ROLLING",
				pattern = "%d{yyyy-MM}",
				fileNamePattern = "%i.gz",
				maxFileSize = "2GB",
				maxHistory = 11,
				totalSizeCap = "1MB",
				append = false
			)
		}
	}
}

From this I conclude that JetBrains' Kotlin style formatter is not enabled at all. Which is disappointing if it was a conscious decision.

Suggestion: apply kotlin style guide (instructions: https://kotlinlang.org/docs/reference/coding-conventions.html#applying-the-style-guide)
make some fixes (e.g. switch spaces to tabs)
export style settings for contributors and attach them to the project.

Provide docs on migration

How to migrate to such kind of declaring sonfig as fu offers??
It is non-intuitive (for me)
Say having config

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {

    private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);

    private final JHipsterProperties jHipsterProperties;

    public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
        this.jHipsterProperties = jHipsterProperties;
    }

    @Override
    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        log.debug("Creating Async Task Executor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
        executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
        executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
        executor.setThreadNamePrefix("cip-old-Executor-");
        return new ExceptionHandlingAsyncTaskExecutor(executor);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

and

@Configuration
@EnableJpaRepositories("com.psg.cip.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement
@EnableElasticsearchRepositories("com.psg.cip.repository.search")
public class DatabaseConfiguration {

    private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);

    private final Environment env;

    private final CacheManager cacheManager;

    public DatabaseConfiguration(Environment env, CacheManager cacheManager) {
        this.env = env;
        this.cacheManager = cacheManager;
    }

    /**
     * Open the TCP port for the H2 database, so it is available remotely.
     *
     * @return the H2 database TCP server
     * @throws SQLException if the server failed to start
     */
    @Bean(initMethod = "start", destroyMethod = "stop")
    @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
    public Object h2TCPServer() throws SQLException {
        try {
            // We don't want to include H2 when we are packaging for the "prod" profile and won't
            // actually need it, so we have to load / invoke things at runtime through reflection.
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            Class<?> serverClass = Class.forName("org.h2.tools.Server", true, loader);
            Method createServer = serverClass.getMethod("createTcpServer", String[].class);
            return createServer.invoke(null, new Object[]{new String[]{"-tcp", "-tcpAllowOthers"}});

        } catch (ClassNotFoundException | LinkageError e) {
            throw new RuntimeException("Failed to load and initialize org.h2.tools.Server", e);

        } catch (SecurityException | NoSuchMethodException e) {
            throw new RuntimeException("Failed to get method org.h2.tools.Server.createTcpServer()", e);

        } catch (IllegalAccessException | IllegalArgumentException e) {
            throw new RuntimeException("Failed to invoke org.h2.tools.Server.createTcpServer()", e);

        } catch (InvocationTargetException e) {
            Throwable t = e.getTargetException();
            if (t instanceof SQLException) {
                throw (SQLException) t;
            }
            throw new RuntimeException("Unchecked exception in org.h2.tools.Server.createTcpServer()", t);
        }
    }

    @Bean
    public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor,
                                     DataSource dataSource, LiquibaseProperties liquibaseProperties) {

        // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
        SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog("classpath:config/liquibase/master.xml");
        liquibase.setContexts(liquibaseProperties.getContexts());
        liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
        liquibase.setDropFirst(liquibaseProperties.isDropFirst());
        if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
            liquibase.setShouldRun(false);
        } else {
            liquibase.setShouldRun(liquibaseProperties.isEnabled());
            log.debug("Configuring Liquibase");
        }
        return liquibase;
    }
}

how to "translate" this to fu ?

doc: availability of the jackson module for the Webflux client

the doc about the Jackson module mentions:

(and very soon on WebFlux client)

but the webflux module example seems to use it already:

        client {
            codecs {
                jackson()
            }
        }

So, if it is already available on the client, the Jackson doc should be updated. If it isn't, the webflusx example could add a comment specifying that the jackson codec sn't actually available on the client yet.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.