All Projects → cuba-rnd → spring-script-repositories

cuba-rnd / spring-script-repositories

Licence: Apache-2.0 license
Spring library for script execution repositories management

Programming Languages

java
68154 projects - #9 most used programming language
groovy
2714 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to spring-script-repositories

Nacos Spring Project
Nacos ECO Project for Spring Framework
Stars: ✭ 614 (+1880.65%)
Mutual labels:  springframework
Open Smart Grid Platform
This repository combines the code from and supersedes the prior existing Shared, Platform, Protocol-Adapter-OSLP, Protocol-Adapter-IEC61850, Protocol-Adapter-DLMS, PublicLightingDemoApp and Integration-Tests repositories. The old repositories have been kept online for now in readonly mode to preserve the historical information.
Stars: ✭ 55 (+77.42%)
Mutual labels:  springframework
Shopizer
Shopizer java e-commerce software
Stars: ✭ 2,541 (+8096.77%)
Mutual labels:  springframework
Mini Spring
mini-spring是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,代码极度简化,保留spring的核心功能,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。
Stars: ✭ 698 (+2151.61%)
Mutual labels:  springframework
Javaee7 Petclinic
Java EE 7 Petclinic
Stars: ✭ 31 (+0%)
Mutual labels:  springframework
Spring Cloud Flycloud
🔥🔥🔥FlyClould 微服务实战项目框架,在该框架中,包括了用 Spring Cloud 构建微服务的一系列基本组件和框架,对于后台服务框架的搭建有很大的参考价值,大家可以参考甚至稍加修改可以直接应用于自己的实际的项目开发中,该项目没有采用Maven进行项目构建,Maven通过xml进行依赖管理,导致整个配置文件太过臃肿,另外灵活性也不是很强,所以我采用Gradle进行项目构建和依赖管理,在FlyTour项目中我们见证了Gradle的强大,通过简单的一些配置就可以轻松的实现组件化的功能。该项目共有11个Module工程。其中10个位微服务工程,这10个微服务工程构成了一个完整的微服务系统,微服务系统包含了8个基础服务,提供了一整套微服务治理功能,他们分别是配置中心module_c…
Stars: ✭ 1,514 (+4783.87%)
Mutual labels:  springframework
Ddd With Spring
Code examples for my conference talk on implementing ddd with spring
Stars: ✭ 448 (+1345.16%)
Mutual labels:  springframework
small-rpc
🔥基于netty和hessian的一个轻量级RPC调用框架
Stars: ✭ 21 (-32.26%)
Mutual labels:  springframework
Mycollab
An open source, free, high performance, stable and secure Java Application Business Platform of Project Management and Document
Stars: ✭ 1,063 (+3329.03%)
Mutual labels:  springframework
Sfg Blog Posts
Source code examples for blog posts
Stars: ✭ 125 (+303.23%)
Mutual labels:  springframework
Search Spring Boot Starter
ElasticSearch封装基于ES版本6.4.2,极大简化了ES操作难度
Stars: ✭ 23 (-25.81%)
Mutual labels:  springframework
Spring Mvc Thymeleaf Crud
Spring MVC CRUD Application with Thymeleaf, HTML5, CSS3 and Bootstrap
Stars: ✭ 14 (-54.84%)
Mutual labels:  springframework
Spring Framework 4 Reference
Chinese translation of the Spring Framework 4.x Reference Documentation (https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/html/) .中文翻译《Spring Framework 4.x参考文档》
Stars: ✭ 1,478 (+4667.74%)
Mutual labels:  springframework
Springboot
Spring Boot chinese document. Spring Boot 2.1.5 中文文档
Stars: ✭ 703 (+2167.74%)
Mutual labels:  springframework
Springboot Practice
SpringBoot practice
Stars: ✭ 234 (+654.84%)
Mutual labels:  springframework
Nacos Spring Boot Project
Nacos ECO Project for Spring Boot
Stars: ✭ 508 (+1538.71%)
Mutual labels:  springframework
Springboard
Spring Boot based production grade starter kit.
Stars: ✭ 59 (+90.32%)
Mutual labels:  springframework
thinking-in-spring
Spring source code reading
Stars: ✭ 105 (+238.71%)
Mutual labels:  springframework
Spring Framework Petclinic
A Spring Framework application based on JSP, Spring MVC, Spring Data JPA, Hibernate and JDBC
Stars: ✭ 251 (+709.68%)
Mutual labels:  springframework
Ssm Demo
🍌Spring+SpringMVC+Mybatis+easyUI实现简单的后台管理系统
Stars: ✭ 1,639 (+5187.1%)
Mutual labels:  springframework

Script Repository Interface

Scripting in java applications is not a rare thing. Sometimes you need to extend your current business logic or add some application management logic. It is very useful since business logic might not be well-defined at the moment of an application's development, or you need to change it frequently without redeploying the application.

Scripting adds flexibility to an application, but also it adds some challenges:

  1. Usually scripts are scattered along the application, so it is quite hard to manage numerous GroovyShell calls.
  2. Scripts usually do not provide any information about input parameters: names and types as well as about output values.

The purpose of this library is to add some order into scripting extension points.

The idea behind this library is simple. A developer creates an interface and links its methods to scripts using annotations.

This approach adds "type-safety" to the process of passing script parameters and a developer will know what will be a type of the script evaluation result.

Usage

To start working with the script repositories, you need to do the following:

  1. Specify repository for library and add it as a dependency in your project build file

    repositories {
        ...
        maven {
            url "https://cuba-platform.bintray.com/labs"
        }
    }
    
    ...
    
    dependencies {
        ...
    	compile 'com.haulmont.scripting:spring-script-repositories:0.1.1'
    }

    Please note that the library's jar file should be placed near application jar files. E.g. if you use tomcat, please put this file to deployed application's WEB-INF/lib folder not to tomcat shared libs. We need it to use a correct classloader for proxy creation.

  2. Define script repository interfaces

    @ScriptRepository
    public interface CustomerScriptRepository {
    
        @GroovyScript
        String renameCustomer(@ScriptParam("customerId") UUID customerId, @ScriptParam("newName") String newName);
    
        @GroovyScript
        Customer createCustomer(@ScriptParam("name") String name, @ScriptParam("birthDate") Date birthDate);
    }

    You can use default implementations in repository interfaces if you want to start quickly without writing scripts for methods.

  3. Define root folder where your scripts will be located by defining groovy.script.source.root.path property in application.properties file:

    groovy.script.source.root.path=classpath:scripts

    Prefixes classpath:, file:, jar: can be used. If source root path is not specified, the library will use default value: classpath:com/haulmont/scripting/scripts

  4. Implement scripts that should be executed and save them in script source root folder. By default, they should be named using pattern InterfaceName.methodName.groovy. So for the example described in p. 2 there will be two files:

    1. CustomerScriptRepository.renameCustomer.groovy
    2. CustomerScriptRepository.createCustomer.groovy

    In your scripts you can use parameters defined in interface's method signatures, parameter names should match those defined in @ScriptParam annotation. For example, for method createCustomer script may look like the following:

    Customer c = new Customer()
    c.setId(UUID.randomUUID())
    c.setName(name)
    c.setBirthDate(birthDate)
    return c

    Parameters name and birthdate will be substituted based on values passed by a caller.

  5. Enable scripting repositories in your application by adding @EnableScriptRepositories annotation to your application configuration and specify path list where your repository interfaces are located.

    @Configuration
    @EnableScriptRepositories(basePackages = {"com.example", "com.sample"})
    public class ExampleConfig {
    }
  6. Inject the interface into proper services and use it as "regular" bean.

    public class CustomerService {
        
        @Autowired
        private CustomerScriptRepository customerScriptRepository;
    
    	public Customer createNew(String name, Date birthDate) {
             return customerScriptRepository.createCustomer(name, birthDate);
    	}    
    }

So it should be pretty easy to get started with the library. By default, it supports Groovy and JavaScript, but it is quite easy to add any scripting language to it. Below is the explanation of the library's internals and configuration.

Internals

The library provides the following:

Marker annotation for script repostitory interfaces.

public @interface ScriptRepository {
   String description() default "";
}

Annotation to link interface method to a script source code. You need to provide bean names for script provider bean and script evaluator bean.

public @interface ScriptMethod {
   String providerBeanName() default "groovyResourceProvider";
   String evaluatorBeanName() default "groovyJsrEvaluator";
   long timeout() default -1L;
   String description() default "";
}

Interface for script provider:

public interface ScriptProvider {
    ScriptSource getScript(Method method);
}

The implementation should be able to find script source text based on scripted method's signature. As an example, the library provides a default implementation GroovyScriptFileProvider for a provider that reads text files from a source root.

Interface for script evaluator - it's a standard Spring Framework class:

public interface ScriptEvaluator {
	Object evaluate(ScriptSource script) throws ScriptCompilationException;
	Object evaluate(ScriptSource script, Map<String, Object> arguments) throws ScriptCompilationException;
}

The implementation just uses script text and invokes it using parameters map. There is a default evaluator implementation GroovyScriptJsrValuator that uses JRE's JSR-223 engine to execute Groovy scripts.

Since parameters names are important and java compiler erase actual parameter names from .class file (unless you enable "keep debug information" option during compilation), the library provides annotation for method parameters that let us to use meaningful parameter names in script instead of "arg0, arg1, etc."

public @interface ScriptParam {
    String value();
}

More examples

You can find examples in test classes. They include custom script provider and custom annotation configuration.

Implementation

The library creates dynamic proxies for repository interfaces marked with @ScriptRepository annotation. All methods in this repository must be marked with @ScriptMethod (or custom annotation). All interfaces marked with @ScriptRepository annotation will be published in Spring's context and can be injected into other spring beans.

When an interface method is called, the proxy invokes provider to get method script text and then evaluator to evaluate the result.

Timeout Support

You can specify timeout either in @ScriptMethod annotation or in custom one to be able to stop script execution if needed. It is useful if you deal with resources like files or database connections either in your provider or in an evaluator. If you want to implement such a bean, you need to either:

  1. Publish the bean as a PROTOTYPE
  2. Store a reference to the closeable resource in class member
  3. Implement TimeoutAware interface and its cancel() method where all closeable resources should be closed. (see com.haulmont.scripting.core.test.database.GroovyScriptDbProvider) as an example.

Or you can try to use ThreadLocal class members to store a reference to a closeable resource.

Configuration

In the project itself you can use two configuration options: annotations and XML.

Annotations configuration

If you plan to use your own implementation for script provider and/or script evaluator (e.g. for JavaScript), you can specify their spring bean names in @ScriptMethod annotation:

@ScriptMethod(providerBeanName = "jsFileProvider", evaluatorBeanName = "jsExecutor")

To avoid copying and pasting this code across the project you can create your own annotation and use it in your project:

@Target(ElementType.METHOD)
@ScriptMethod(providerBeanName = "jsFileProvider", evaluatorBeanName = "jsExecutor")
public @interface JsScript {
}

XML Configuration

You can also configure both package scanning and custom annotations using XML in spring configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:repo="http://www.cuba-platform.org/schema/script/repositories"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.cuba-platform.org/schema/script/repositories http://www.cuba-platform.org/schema/script/repositories/script-repositories.xsd">

    <repo:script-repositories>
        <repo:base-packages>
            <repo:base-package>com.example</repo:base-package>
            <repo:base-package>com.sample</repo:base-package>
        </repo:base-packages>
        <repo:annotations-config>
            <repo:annotation-mapping annotation-class="com.example.JsScript"
                                     provider-bean-name="jsFileProvider"
                                     evaluator-bean-name="jsExecutor"/>
        </repo:annotations-config>
    </repo:script-repositories>

    <!-- Annotation-based beans -->
    <context:component-scan base-package="com.example.beans"/>

</beans>

Mixed configuration

In case of mixed configuration - Annotations+XML, config parameters will be merged, therefore it is not recommended to configure the same custom annotation in two places because one of the configuration will override another.

References and thanks

There is a good article by Anton Arhipov that helped us a lot with implementation of this library.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].