├── .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 getAddresses() { 15 | return get(ADDRESSES); 16 | } 17 | 18 | public void setAddresses(List addresses) { 19 | 20 | } 21 | 22 | private Map> lists = new ConcurrentHashMap>(); 23 | 24 | public void addBlacklist(String key, List items) { 25 | lists.put(key, items); 26 | } 27 | 28 | public List get(String key) { 29 | return lists.get(key); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/oudmaijer/drools/fraud/rules/Errors.java: -------------------------------------------------------------------------------- 1 | package com.oudmaijer.drools.fraud.rules; 2 | 3 | import javax.xml.bind.annotation.XmlElement; 4 | import javax.xml.bind.annotation.XmlRootElement; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by Stephan on 19-06-14. 10 | */ 11 | @XmlRootElement 12 | public class Errors { 13 | 14 | private java.util.List messages = new ArrayList(); 15 | 16 | public void reject(Order order) { 17 | reject("Rejected without reason: ", order); 18 | } 19 | 20 | public void reject(String messsage, Order order) { 21 | messages.add(messsage +" - "+ order); 22 | } 23 | 24 | public void suspicious(Order order) { 25 | messages.add("Suspicious order: "+ order); 26 | } 27 | 28 | public void suspicious(String message, Order order) { 29 | messages.add(message +" - "+ order); 30 | } 31 | 32 | public void add(String error) { 33 | messages.add(error); 34 | } 35 | 36 | @XmlElement(name="error") 37 | public List getErrors() { 38 | return messages; 39 | } 40 | 41 | public void setErrors(List errors) { 42 | this.messages = errors; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/oudmaijer/drools/fraud/rules/Order.java: -------------------------------------------------------------------------------- 1 | package com.oudmaijer.drools.fraud.rules; 2 | 3 | import javax.xml.bind.annotation.XmlRootElement; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by Stephan on 18-06-14. 8 | */ 9 | @XmlRootElement 10 | public class Order { 11 | 12 | private String orderId; 13 | private Seller seller; 14 | private Address shipmentAddress; 15 | private List orderItems; 16 | private String paymentType; 17 | 18 | public Order() { 19 | } 20 | 21 | public Order(String orderId, Seller seller, Address shipmentAddress) { 22 | this.orderId = orderId; 23 | this.seller = seller; 24 | this.shipmentAddress = shipmentAddress; 25 | } 26 | 27 | public String getPaymentType() { 28 | return paymentType; 29 | } 30 | 31 | public void setPaymentType(String paymentType) { 32 | this.paymentType = paymentType; 33 | } 34 | 35 | public List getOrderItems() { 36 | return orderItems; 37 | } 38 | 39 | public void setOrderItems(List orderItems) { 40 | this.orderItems = orderItems; 41 | } 42 | 43 | public Address getShipmentAddress() { 44 | return shipmentAddress; 45 | } 46 | 47 | public void setShipmentAddress(Address shipmentAddress) { 48 | this.shipmentAddress = shipmentAddress; 49 | } 50 | 51 | public Seller getSeller() { 52 | return seller; 53 | } 54 | 55 | public void setSeller(Seller seller) { 56 | this.seller = seller; 57 | } 58 | 59 | public String getOrderId() { 60 | return orderId; 61 | } 62 | 63 | public void setOrderId(String orderId) { 64 | this.orderId = orderId; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return "Order{" + 70 | "orderId=" + orderId + 71 | ", seller=" + seller + 72 | ", shipmentAddress=" + shipmentAddress + 73 | ", orderItems=" + orderItems + 74 | '}'; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/oudmaijer/drools/fraud/rules/OrderItem.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 OrderItem { 10 | 11 | public OrderItem() { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/oudmaijer/drools/fraud/rules/RuleParam.java: -------------------------------------------------------------------------------- 1 | package com.oudmaijer.drools.fraud.rules; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * Created by Stephan on 19-06-14. 8 | */ 9 | public class RuleParam { 10 | 11 | public static final String MINIMAL_SELLER_RATING = "MINIMAL_SELLER_RATING"; 12 | 13 | private Map param = new ConcurrentHashMap() {{ 14 | put(MINIMAL_SELLER_RATING, "8"); 15 | }}; 16 | 17 | public Object get(String key) { 18 | return param.get(key); 19 | } 20 | 21 | public Integer getInt(String key) { 22 | return Integer.parseInt(param.get(key)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/oudmaijer/drools/fraud/rules/Seller.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 Seller { 10 | 11 | private Integer rating; 12 | 13 | public Seller() { 14 | } 15 | 16 | public Seller(Integer rating) { 17 | this.rating = rating; 18 | } 19 | 20 | public Integer getRating() { 21 | return rating; 22 | } 23 | 24 | public void setRating(Integer rating) { 25 | this.rating = rating; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "Seller{" + 31 | "rating=" + rating + 32 | '}'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.view.prefix: /WEB-INF/jsp/ 2 | spring.view.suffix: .jsp -------------------------------------------------------------------------------- /src/main/resources/com/oudmaijer/drools/fraud/rules/OrderRuleAddressCheck.drl: -------------------------------------------------------------------------------- 1 | package com.oudmaijer.drools.fraud.rules 2 | 3 | global Errors errors 4 | 5 | rule "Seller shipment address on blacklist" 6 | when 7 | Blacklist($addressBlacklist : addresses) // Expose the addresses blacklist 8 | 9 | $order : Order( shipmentAddress memberOf $addressBlacklist, // Check blacklist rule 10 | paymentType != "02" ) // And whitelist rule 11 | then 12 | errors.reject("This must be fraud!", $order); 13 | end 14 | -------------------------------------------------------------------------------- /src/main/resources/com/oudmaijer/drools/fraud/rules/OrderRuleSellerRating.drl: -------------------------------------------------------------------------------- 1 | package com.oudmaijer.drools.fraud.rules 2 | 3 | global Errors errors 4 | 5 | rule "Seller rating rule" 6 | when 7 | $order : Order() // Expose the order 8 | Seller( rating < 5 ) from $order.seller // Check if seller rating of seller of the order is high enough 9 | then 10 | errors.suspicious($order); 11 | end -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/api.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Swagger UI 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | <%= request.getContextPath() %> 26 | 27 | 66 | 67 | 68 | 69 | 85 | 86 |
 
87 |
88 | 89 | 90 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/error.jsp: -------------------------------------------------------------------------------- 1 | Error! -------------------------------------------------------------------------------- /src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Drools example

5 | 8 |

API docs

9 | 12 |
13 | 14 | -------------------------------------------------------------------------------- /src/test/java/com/oudmaijer/drools/fraud/FraudServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.oudmaijer.drools.fraud; 2 | 3 | import com.oudmaijer.drools.config.DroolsConfig; 4 | import com.oudmaijer.drools.fraud.rules.Address; 5 | import com.oudmaijer.drools.fraud.rules.Errors; 6 | import com.oudmaijer.drools.fraud.rules.Order; 7 | import com.oudmaijer.drools.fraud.rules.Seller; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.test.context.ContextConfiguration; 14 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 15 | import org.springframework.util.StopWatch; 16 | 17 | @RunWith(SpringJUnit4ClassRunner.class) 18 | @ContextConfiguration(classes = DroolsConfig.class) 19 | public class FraudServiceTest { 20 | @Autowired 21 | private FraudService fraudService; 22 | public Logger log = LoggerFactory.getLogger(FraudServiceTest.class); 23 | 24 | @Test 25 | public void testOrderValidation() { 26 | StopWatch stopWatch = new StopWatch(); 27 | stopWatch.start(); 28 | for (int i = 0; i < 100; i++) { 29 | final boolean first = (i == 0); 30 | new Thread(new Runnable() { 31 | @Override 32 | public void run() { 33 | Errors errors = fraudService.check(new Order("1", new Seller(3), new Address("3452RK", 53))); 34 | if (first) { 35 | log.info("Validated with {} errors {}", errors.getErrors().size(), errors.getErrors()); 36 | } 37 | } 38 | }).run(); 39 | } 40 | stopWatch.stop(); 41 | log.info("Validation of {} took: " + stopWatch.getTotalTimeMillis() + "ms"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /system.properties: -------------------------------------------------------------------------------- 1 | java.runtime.version=1.7 2 | --------------------------------------------------------------------------------