├── .gitignore
├── Procfile
├── README.md
├── pom.xml
├── src
├── main
│ ├── java
│ │ └── com
│ │ │ └── oudmaijer
│ │ │ └── drools
│ │ │ ├── FraudApplication.java
│ │ │ ├── config
│ │ │ ├── DroolsConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ └── fraud
│ │ │ ├── ExceptionHandlerController.java
│ │ │ ├── FraudController.java
│ │ │ ├── FraudRepository.java
│ │ │ ├── FraudService.java
│ │ │ └── rules
│ │ │ ├── Address.java
│ │ │ ├── Blacklist.java
│ │ │ ├── Errors.java
│ │ │ ├── Order.java
│ │ │ ├── OrderItem.java
│ │ │ ├── RuleParam.java
│ │ │ └── Seller.java
│ ├── resources
│ │ ├── application.properties
│ │ ├── com
│ │ │ └── oudmaijer
│ │ │ │ └── drools
│ │ │ │ └── fraud
│ │ │ │ └── rules
│ │ │ │ ├── OrderRuleAddressCheck.drl
│ │ │ │ └── OrderRuleSellerRating.drl
│ │ └── logback.xml
│ └── webapp
│ │ ├── WEB-INF
│ │ └── jsp
│ │ │ ├── api.jsp
│ │ │ └── error.jsp
│ │ └── index.html
└── test
│ └── java
│ └── com
│ └── oudmaijer
│ └── drools
│ └── fraud
│ └── FraudServiceTest.java
└── system.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | *.jar
3 | *.war
4 | *.class
5 | *.iml
6 | *.ipr
7 | *.iws
8 | .idea/
9 | .DS_Store
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: java $JAVA_OPTS -jar target/*.war
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | drools
2 | ======
3 |
4 | Spring boot drools demo app
5 |
6 | ## How to run
7 |
8 | ```
9 | mvn spring-boot:run
10 | ```
11 |
12 | ## Using
13 |
14 | Try the drools offer check using the following URL:
15 |
16 | Go to the Swagger API page: [http://localhost:8080/sdoc.jsp#!/fraud/checkOrder](http://localhost:8080/sdoc.jsp#!/fraud/checkOrder)
17 |
18 | Paste the following offer:
19 |
20 | ```json
21 | {
22 | "offerId": "1",
23 | "seller": {
24 | "rating": "3"
25 | }
26 | }
27 | ```
28 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.springframework.boot
9 | spring-boot-starter-parent
10 | 1.1.2.RELEASE
11 |
12 |
13 | war
14 | com.oudmaijer
15 | drools-spring
16 | 1.0-SNAPSHOT
17 |
18 |
19 | 1.7
20 | 6.1.0.CR1
21 | 3.0.2
22 | com.oudmaijer.drools.FraudApplication
23 |
24 |
25 |
26 |
27 | javax.inject
28 | javax.inject
29 | 1
30 |
31 |
32 | javax.servlet
33 | javax.servlet-api
34 | 3.0.1
35 | provided
36 |
37 |
38 |
39 |
40 | org.kie
41 | kie-api
42 | ${kie.version}
43 |
44 |
45 | org.kie
46 | kie-internal
47 | ${kie.version}
48 |
49 |
50 | org.drools
51 | drools-core
52 | ${kie.version}
53 |
54 |
55 | org.drools
56 | drools-compiler
57 | ${kie.version}
58 |
59 |
60 | org.kie
61 | kie-spring
62 | ${kie.version}
63 |
64 |
65 |
66 |
67 | org.springframework.boot
68 | spring-boot-starter-web
69 |
70 |
71 | org.springframework.boot
72 | spring-boot-starter-actuator
73 |
74 |
75 | org.springframework
76 | spring-messaging
77 |
78 |
79 | com.codahale.metrics
80 | metrics-core
81 |
82 |
83 | org.springframework.boot
84 | spring-boot-starter-tomcat
85 | provided
86 |
87 |
88 | org.apache.tomcat.embed
89 | tomcat-embed-jasper
90 | provided
91 |
92 |
93 | javax.servlet
94 | jstl
95 |
96 |
97 |
98 |
99 | com.fasterxml.jackson.core
100 | jackson-databind
101 |
102 |
103 | com.fasterxml.jackson.core
104 | jackson-annotations
105 |
106 |
107 | com.fasterxml.jackson.core
108 | jackson-core
109 |
110 |
111 |
112 | commons-io
113 | commons-io
114 | 2.4
115 |
116 |
117 | org.springframework.boot
118 | spring-boot-starter-test
119 | test
120 |
121 |
122 |
123 |
124 | com.codahale.metrics
125 | metrics-core
126 | ${codahale.version}
127 |
128 |
129 | com.codahale.metrics
130 | metrics-annotation
131 | ${codahale.version}
132 |
133 |
134 |
135 |
136 | com.mangofactory
137 | swagger-springmvc
138 | 0.8.4
139 |
140 |
141 | org.ajar
142 | swagger-spring-mvc-ui
143 | 0.2
144 |
145 |
146 |
147 |
148 | ch.qos.logback
149 | logback-classic
150 | 1.0.13
151 |
152 |
153 | org.slf4j
154 | slf4j-api
155 | 1.7.5
156 |
157 |
158 |
159 |
160 |
161 |
162 | org.apache.tomcat.maven
163 | tomcat7-maven-plugin
164 | 2.2
165 |
166 | /
167 |
168 |
169 |
170 | org.apache.maven.plugins
171 | maven-war-plugin
172 |
173 |
174 | org.apache.maven.plugins
175 | maven-compiler-plugin
176 |
177 | ${java.version}
178 | ${java.version}
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 | oss-jfrog-artifactory
191 | oss-jfrog-artifactory-releases
192 | http://oss.jfrog.org/artifactory/oss-release-local
193 |
194 |
195 |
196 |
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/FraudApplication.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools;
2 |
3 | import com.mangofactory.swagger.plugin.EnableSwagger;
4 | import com.oudmaijer.drools.config.DroolsConfig;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
7 | import org.springframework.boot.builder.SpringApplicationBuilder;
8 | import org.springframework.boot.context.web.SpringBootServletInitializer;
9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.context.annotation.Import;
11 |
12 | @Configuration
13 | @EnableAutoConfiguration
14 | @EnableSwagger
15 | @Import({DroolsConfig.class})
16 | public class FraudApplication extends SpringBootServletInitializer {
17 |
18 | @Override
19 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
20 | return application.sources(FraudApplication.class);
21 | }
22 |
23 | public static void main(String[] args) {
24 | SpringApplication.run(FraudApplication.class, args);
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/config/DroolsConfig.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.config;
2 |
3 | import com.google.common.base.Charsets;
4 | import com.google.common.io.Files;
5 | import org.apache.commons.io.IOUtils;
6 | import org.drools.core.io.impl.FileSystemResource;
7 | import org.kie.api.KieBase;
8 | import org.kie.api.KieServices;
9 | import org.kie.api.builder.KieBuilder;
10 | import org.kie.api.builder.KieFileSystem;
11 | import org.kie.api.builder.KieModule;
12 | import org.kie.api.builder.KieRepository;
13 | import org.kie.api.builder.ReleaseId;
14 | import org.kie.api.runtime.KieContainer;
15 | import org.springframework.context.annotation.Bean;
16 | import org.springframework.context.annotation.ComponentScan;
17 | import org.springframework.context.annotation.Configuration;
18 | import org.springframework.core.io.Resource;
19 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
20 |
21 | import java.io.File;
22 | import java.io.FileInputStream;
23 | import java.io.FileNotFoundException;
24 | import java.io.IOException;
25 |
26 | /**
27 | * Created by Stephan on 17-06-14.
28 | */
29 | @Configuration
30 | @ComponentScan(basePackages = {"com.oudmaijer.drools.fraud"})
31 | public class DroolsConfig {
32 |
33 | private Resource[] listRules() throws IOException {
34 | PathMatchingResourcePatternResolver pmrs = new PathMatchingResourcePatternResolver();
35 | Resource[] resources = pmrs.getResources("classpath*:com/oudmaijer/**/*.drl");
36 | return resources;
37 | }
38 |
39 | @Bean
40 | public KieContainer kieContainer() throws IOException {
41 | KieServices ks = KieServices.Factory.get();
42 | final KieRepository kr = ks.getRepository();
43 | kr.addKieModule(new KieModule() {
44 | @Override
45 | public ReleaseId getReleaseId() {
46 | return kr.getDefaultReleaseId();
47 | }
48 | });
49 | KieFileSystem kfs = ks.newKieFileSystem();
50 | Resource[] files = listRules();
51 |
52 | for(Resource file : files) {
53 | String myString = IOUtils.toString(file.getInputStream(), "UTF-8");
54 | kfs.write("src/main/resources/"+ file.getFilename(), myString);
55 | }
56 |
57 | KieBuilder kb = ks.newKieBuilder(kfs);
58 | kb.buildAll(); // kieModule is automatically deployed to KieRepository if successfully built.
59 | KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
60 | return kContainer;
61 | }
62 |
63 | @Bean
64 | public KieBase kieBase() throws IOException {
65 | KieBase kieBase = kieContainer().getKieBase();
66 | return kieBase;
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
6 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
7 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
9 | import org.springframework.web.servlet.view.InternalResourceViewResolver;
10 |
11 | /**
12 | * Created by Stephan on 25-06-14.
13 | */
14 | @Configuration
15 | public class SwaggerConfig extends WebMvcConfigurerAdapter {
16 |
17 | @Override
18 | public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
19 | configurer.enable();
20 | }
21 |
22 | @Bean
23 | public InternalResourceViewResolver getInternalResourceViewResolver() {
24 | InternalResourceViewResolver resolver = new InternalResourceViewResolver();
25 | resolver.setPrefix("/WEB-INF/jsp/");
26 | resolver.setSuffix(".jsp");
27 | return resolver;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/fraud/ExceptionHandlerController.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.fraud;
2 |
3 | import org.springframework.web.bind.annotation.ControllerAdvice;
4 | import org.springframework.web.bind.annotation.ExceptionHandler;
5 | import org.springframework.web.servlet.ModelAndView;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import java.util.Date;
9 |
10 | @ControllerAdvice
11 | public class ExceptionHandlerController {
12 |
13 | public static final String DEFAULT_ERROR_VIEW = "error";
14 |
15 | @ExceptionHandler(value = {Exception.class, RuntimeException.class})
16 | public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
17 | ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
18 |
19 | mav.addObject("datetime", new Date());
20 | mav.addObject("exception", e);
21 | mav.addObject("url", request.getRequestURL());
22 | return mav;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/fraud/FraudController.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.fraud;
2 |
3 | import com.oudmaijer.drools.fraud.rules.Errors;
4 | import com.oudmaijer.drools.fraud.rules.Order;
5 | import com.wordnik.swagger.annotations.Api;
6 | import com.wordnik.swagger.annotations.ApiOperation;
7 | import org.springframework.http.MediaType;
8 | import org.springframework.web.bind.annotation.RequestBody;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestMethod;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import javax.inject.Inject;
14 |
15 | @Api(value = "fraud", description = "Fraud and risk service API") // Swagger annotation
16 | @RestController
17 | @RequestMapping("/fraud/check")
18 | public class FraudController {
19 |
20 | private FraudService fraudService;
21 |
22 | @Inject
23 | public FraudController(FraudService fraudService) {
24 | this.fraudService = fraudService;
25 | }
26 |
27 | @ApiOperation("Order fraud check")
28 | @RequestMapping(value = "/order", method = {RequestMethod.POST}, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
29 | public Errors checkOrder(@RequestBody Order order) {
30 | return fraudService.check(order);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/fraud/FraudRepository.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.fraud;
2 |
3 | import com.oudmaijer.drools.fraud.rules.Address;
4 | import com.oudmaijer.drools.fraud.rules.Blacklist;
5 | import com.oudmaijer.drools.fraud.rules.RuleParam;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.ArrayList;
9 |
10 | @Repository
11 | public class FraudRepository {
12 |
13 | // Stuff that we will retrieve from the database. Here now for testing.
14 | private static RuleParam ruleParam = new RuleParam();
15 | private static Blacklist blacklist = new Blacklist();
16 |
17 | static {
18 | blacklist.addBlacklist(Blacklist.ADDRESSES, new ArrayList() {{
19 | add(new Address("3452RK", 53));
20 | }});
21 | }
22 |
23 | public RuleParam getRuleParam() {
24 | return ruleParam;
25 | }
26 |
27 | public Blacklist getBlacklist() {
28 | return blacklist;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/fraud/FraudService.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.fraud;
2 |
3 | import com.codahale.metrics.annotation.ExceptionMetered;
4 | import com.codahale.metrics.annotation.Metered;
5 | import com.oudmaijer.drools.fraud.rules.Errors;
6 | import com.oudmaijer.drools.fraud.rules.Order;
7 | import org.kie.api.KieBase;
8 | import org.kie.api.runtime.KieSession;
9 | import org.springframework.stereotype.Service;
10 |
11 | import javax.inject.Inject;
12 |
13 | @Service
14 | public class FraudService {
15 |
16 | private final KieBase kbase;
17 | private final FraudRepository fraudRepository;
18 |
19 | @Inject
20 | public FraudService(KieBase kbase, FraudRepository fraudRepository) {
21 | this.kbase = kbase;
22 | this.fraudRepository = fraudRepository;
23 | }
24 |
25 | @Metered
26 | @ExceptionMetered
27 | public Errors check(Order order) {
28 | KieSession ksession = kbase.newKieSession();
29 |
30 | // Setup globals
31 | Errors errors = new Errors();
32 | addGlobalObjectsToSession(ksession, errors);
33 |
34 | // Add order to be validated
35 | ksession.insert(fraudRepository.getBlacklist());
36 | ksession.insert(order);
37 |
38 | // Fire all rules and destroy session.
39 | ksession.fireAllRules();
40 | ksession.destroy();
41 |
42 | // Return result
43 | return errors;
44 | }
45 |
46 | private void addGlobalObjectsToSession(KieSession kieSession, Errors errors) {
47 | kieSession.setGlobal("errors", errors);
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/fraud/rules/Address.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.fraud.rules;
2 |
3 | import javax.xml.bind.annotation.XmlRootElement;
4 |
5 | /**
6 | * Created by Stephan on 19-06-14.
7 | */
8 | @XmlRootElement
9 | public class Address {
10 |
11 | private String zip;
12 | private int houseNumber;
13 |
14 | public Address() {
15 | }
16 |
17 | public Address(String zip, int houseNumber) {
18 | this.zip = zip;
19 | this.houseNumber = houseNumber;
20 | }
21 |
22 | public String getZip() {
23 | return zip;
24 | }
25 |
26 | public void setZip(String zip) {
27 | this.zip = zip;
28 | }
29 |
30 | public int getHouseNumber() {
31 | return houseNumber;
32 | }
33 |
34 | public void setHouseNumber(int houseNumber) {
35 | this.houseNumber = houseNumber;
36 | }
37 |
38 | @Override
39 | public boolean equals(Object o) {
40 | if (this == o) return true;
41 | if (o == null || getClass() != o.getClass()) return false;
42 |
43 | Address address = (Address) o;
44 |
45 | if (houseNumber != address.houseNumber) return false;
46 | if (!zip.equals(address.zip)) return false;
47 |
48 | return true;
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | int result = zip.hashCode();
54 | result = 31 * result + houseNumber;
55 | return result;
56 | }
57 |
58 | @Override
59 | public String toString() {
60 | return "Address{" +
61 | "zip='" + zip + '\'' +
62 | ", houseNumber=" + houseNumber +
63 | '}';
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/oudmaijer/drools/fraud/rules/Blacklist.java:
--------------------------------------------------------------------------------
1 | package com.oudmaijer.drools.fraud.rules;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | import java.util.concurrent.ConcurrentHashMap;
6 |
7 | /**
8 | * Created by Stephan on 19-06-14.
9 | */
10 | public class Blacklist {
11 |
12 | public static final String ADDRESSES = "addresses";
13 |
14 | public List