diff --git a/cola-framework-common/pom.xml b/cola-framework-common/pom.xml new file mode 100644 index 000000000..e7a66422d --- /dev/null +++ b/cola-framework-common/pom.xml @@ -0,0 +1,134 @@ + + + 4.0.0 + + com.aliyun + cola-common + jar + 3.0.0 + + cola common + https://github.com/alibaba/COLA + Cola framework common components + + + + sonatype-nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + GNU Lesser General Public License v2.1 + https://github.com/alibaba/COLA/blob/master/LICENSE + repo + + + + + scm:git:https://github.com/alibaba/COLA.git + scm:git:https://github.com/alibaba/COLA.git + https://github.com/alibaba/COLA + + + + + Frank + Frank Zhang + 25216348@qq.com + + + + + 1.8 + 1.8 + 1.8 + UTF-8 + UTF-8 + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + verify + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + UTF-8 + none + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + sonatype-nexus-staging + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + \ No newline at end of file diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/ClientObject.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/ClientObject.java new file mode 100644 index 000000000..95a05511b --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/ClientObject.java @@ -0,0 +1,39 @@ +package com.alibaba.cola.dto; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * This is the object communicate with Client. + * The clients could be view layer or other HSF Consumers + * @author fulan.zjf 2017-10-27 PM 12:19:15 + */ +public abstract class ClientObject implements Serializable{ + + private static final long serialVersionUID = 1L; + + /** + * This is for extended values + */ + protected Map extValues = new HashMap(); + + public Object getExtField(String key){ + if(extValues != null){ + return extValues.get(key); + } + return null; + } + + public void putExtField(String fieldName, Object value){ + this.extValues.put(fieldName, value); + } + + public Map getExtValues() { + return extValues; + } + + public void setExtValues(Map extValues) { + this.extValues = extValues; + } +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/Command.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/Command.java new file mode 100644 index 000000000..138054b12 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/Command.java @@ -0,0 +1,24 @@ +package com.alibaba.cola.dto; + +import com.alibaba.cola.extension.BizScenario; + +/** + * Command stands for a request from Client. + * According CommandExecutor will help to handle the business logic. This is a classic Command Pattern + * + * @author fulan.zjf 2017年10月27日 下午12:28:24 + */ +public abstract class Command extends DTO{ + + private static final long serialVersionUID = 1L; + + private BizScenario bizScenario; + + public BizScenario getBizScenario() { + return bizScenario; + } + + public void setBizScenario(BizScenario bizScenario) { + this.bizScenario = bizScenario; + } +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/DTO.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/DTO.java new file mode 100644 index 000000000..915db72ea --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/DTO.java @@ -0,0 +1,16 @@ +package com.alibaba.cola.dto; + +import java.io.Serializable; + +/** + * Data Transfer object, including Command, Query and Response, + * + * Command and Query is CQRS concept. + * + * @author fulan.zjf 2017年10月21日 下午8:53:55 + */ +public abstract class DTO implements Serializable{ + + private static final long serialVersionUID = 1L; + +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/ErrorCodeI.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/ErrorCodeI.java new file mode 100644 index 000000000..4917ecf07 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/ErrorCodeI.java @@ -0,0 +1,14 @@ +package com.alibaba.cola.dto; + +/** + * Extends your error codes in your App by implements this Interface. + * + * Created by fulan.zjf on 2017/12/18. + */ +public interface ErrorCodeI { + + public String getErrCode(); + + public String getErrDesc(); + +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/MultiResponse.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/MultiResponse.java new file mode 100644 index 000000000..6a69f94e6 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/MultiResponse.java @@ -0,0 +1,64 @@ +package com.alibaba.cola.dto; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Response with batch record to return, + * usually use in page query or conditional query + *

+ * Created by Danny.Lee on 2017/11/1. + */ +public class MultiResponse extends Response { + + private int total; + + private Collection data; + + public static MultiResponse of(Collection data, int total) { + MultiResponse multiResponse = new MultiResponse<>(); + multiResponse.setSuccess(true); + multiResponse.setData(data); + multiResponse.setTotal(total); + return multiResponse; + } + + public static MultiResponse ofWithoutTotal(Collection data) { + return of(data,0); + } + + + public int getTotal() { + return total; + } + + + public void setTotal(int total) { + this.total = total; + } + + public List getData() { + return null == data ? new ArrayList<>() : new ArrayList<>(data); + } + + + public void setData(Collection data) { + this.data = data; + } + + public static MultiResponse buildFailure(String errCode, String errMessage) { + MultiResponse response = new MultiResponse(); + response.setSuccess(false); + response.setErrCode(errCode); + response.setErrMessage(errMessage); + return response; + } + + public static MultiResponse buildSuccess(){ + MultiResponse response = new MultiResponse(); + response.setSuccess(true); + return response; + } + +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/OrderDesc.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/OrderDesc.java new file mode 100644 index 000000000..ae82c66fa --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/OrderDesc.java @@ -0,0 +1,30 @@ +package com.alibaba.cola.dto; + +import java.io.Serializable; + +/** + * Order Description + * + * @author Danny.Lee 2017/12/19 + */ +public class OrderDesc implements Serializable{ + + private String col; + private boolean asc = true; + + public String getCol() { + return col; + } + + public void setCol(String col) { + this.col = col; + } + + public boolean isAsc() { + return asc; + } + + public void setAsc(boolean asc) { + this.asc = asc; + } +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/PageQuery.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/PageQuery.java new file mode 100644 index 000000000..1b310926b --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/PageQuery.java @@ -0,0 +1,57 @@ +package com.alibaba.cola.dto; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * page query + *

+ * Created by Danny.Lee on 2017/11/1. + */ +public abstract class PageQuery extends Query { + + private int pageNum = 1; + private int pageSize = 10; + private boolean needTotalCount = true; + private List orderDescs; + + public int getPageNum() { + return pageNum; + } + + public void setPageNum(int pageNum) { + this.pageNum = pageNum; + } + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public boolean isNeedTotalCount() { + return needTotalCount; + } + + public void setNeedTotalCount(boolean needTotalCount) { + this.needTotalCount = needTotalCount; + } + + public List getOrderDescs() { + return orderDescs; + } + + public void addOrderDesc(OrderDesc orderDesc) { + if (null == orderDescs) { + orderDescs = new ArrayList<>(); + } + orderDescs.add(orderDesc); + } + + public int getOffset() { + return pageNum > 0 ? (pageNum - 1) * pageSize : 0; + } +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/Query.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/Query.java new file mode 100644 index 000000000..20f987b6e --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/Query.java @@ -0,0 +1,13 @@ +package com.alibaba.cola.dto; + +/** + * + * Query is a special Command which will directly call DataTunnel for data objects + * + * @author fulan.zjf 2017年10月22日 下午7:26:49 + */ +public abstract class Query extends Command{ + + private static final long serialVersionUID = 1L; + +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/Response.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/Response.java new file mode 100644 index 000000000..ecd619426 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/Response.java @@ -0,0 +1,67 @@ +package com.alibaba.cola.dto; + +/** + * Response to caller + * + * @author fulan.zjf 2017年10月21日 下午8:53:17 + */ +public class Response extends DTO{ + + private static final long serialVersionUID = 1L; + + private boolean isSuccess; + + private String errCode; + + private String errMessage; + + public boolean isSuccess() { + return isSuccess; + } + + + public void setSuccess(boolean isSuccess) { + this.isSuccess = isSuccess; + } + + + public String getErrCode() { + return errCode; + } + + + public void setErrCode(String errCode) { + this.errCode = errCode; + } + + + public String getErrMessage() { + return errMessage; + } + + + public void setErrMessage(String errMessage) { + this.errMessage = errMessage; + } + + + @Override + public String toString() { + return "Response [isSuccess=" + isSuccess + ", errCode=" + errCode + ", errMessage=" + errMessage + "]"; + } + + public static Response buildFailure(String errCode, String errMessage) { + Response response = new Response(); + response.setSuccess(false); + response.setErrCode(errCode); + response.setErrMessage(errMessage); + return response; + } + + public static Response buildSuccess(){ + Response response = new Response(); + response.setSuccess(true); + return response; + } + +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/dto/SingleResponse.java b/cola-framework-common/src/main/java/com/alibaba/cola/dto/SingleResponse.java new file mode 100644 index 000000000..ebcd04622 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/dto/SingleResponse.java @@ -0,0 +1,42 @@ +package com.alibaba.cola.dto; + +/** + * Response with single record to return + *

+ * Created by Danny.Lee on 2017/11/1. + */ + +public class SingleResponse extends Response { + + private T data; + + public static SingleResponse of(T data) { + SingleResponse singleResponse = new SingleResponse<>(); + singleResponse.setSuccess(true); + singleResponse.setData(data); + return singleResponse; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public static SingleResponse buildFailure(String errCode, String errMessage) { + SingleResponse response = new SingleResponse(); + response.setSuccess(false); + response.setErrCode(errCode); + response.setErrMessage(errMessage); + return response; + } + + public static SingleResponse buildSuccess(){ + SingleResponse response = new SingleResponse(); + response.setSuccess(true); + return response; + } + +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/event/DomainEventI.java b/cola-framework-common/src/main/java/com/alibaba/cola/event/DomainEventI.java new file mode 100644 index 000000000..7ef1d77ab --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/event/DomainEventI.java @@ -0,0 +1,16 @@ +package com.alibaba.cola.event; + +/** + * Domain Event (领域事件) + * + * 命名规则:实体名+动词的过去时态+Event + * + * 比如CustomerCreated 表示创建完客户发送出来的领域事件 + * 比如ContactAdded 表示添加完联系人发送出来的领域事件 + * 比如OpportunityTransferred 表示机会转移完发送出来的领域事件 + * + * @author Frank Zhang + * @date 2018-07-30 11:15 AM + */ +public interface DomainEventI extends EventI { +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/event/EventI.java b/cola-framework-common/src/main/java/com/alibaba/cola/event/EventI.java new file mode 100644 index 000000000..a39ba42e3 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/event/EventI.java @@ -0,0 +1,8 @@ +package com.alibaba.cola.event; + +/** + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +public interface EventI { +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/event/MessageQueueEventI.java b/cola-framework-common/src/main/java/com/alibaba/cola/event/MessageQueueEventI.java new file mode 100644 index 000000000..bbed0e3ba --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/event/MessageQueueEventI.java @@ -0,0 +1,11 @@ +package com.alibaba.cola.event; + +/** + * @author: caiqiang.w + * @date: 2019/2/14 + * @description: + */ +public interface MessageQueueEventI extends EventI { + public String getEventType(); + public String getEventTopic(); +} diff --git a/cola-framework-common/src/main/java/com/alibaba/cola/extension/BizScenario.java b/cola-framework-common/src/main/java/com/alibaba/cola/extension/BizScenario.java new file mode 100644 index 000000000..c215b1919 --- /dev/null +++ b/cola-framework-common/src/main/java/com/alibaba/cola/extension/BizScenario.java @@ -0,0 +1,60 @@ +package com.alibaba.cola.extension; + + +/** + * BizScenario(业务场景)= bizId + useCase + scenario, which can uniquely identify a user scenario. + * + * @author Frank Zhang + * @date 2019-08-20 12:07 + */ +public class BizScenario { + public final static String DEFAULT_BIZ_ID = "defaultBizId"; + public final static String DEFAULT_USE_CASE = "defaultUseCase"; + public final static String DEFAULT_SCENARIO = "defaultScenario"; + private final static String DOT_SEPARATOR = "."; + + /** + * bizId is used to identify a business, such as "tmall", it's nullable if there is only one biz + */ + private String bizId = DEFAULT_BIZ_ID; + + /** + * useCase is used to identify a use case, such as "placeOrder", can not be null + */ + private String useCase = DEFAULT_USE_CASE; + + /** + * scenario is used to identify a use case, such as "88vip","normal", can not be null + */ + private String scenario = DEFAULT_SCENARIO; + + /** + * For above case, the BizScenario will be "tmall.placeOrder.88vip", + * with this code, we can provide extension processing other than "tmall.placeOrder.normal" scenario. + * + * @return + */ + public String getUniqueIdentity(){ + return bizId + DOT_SEPARATOR + useCase + DOT_SEPARATOR + scenario; + } + + public static BizScenario valueOf(String bizId, String useCase, String scenario){ + BizScenario bizScenario = new BizScenario(); + bizScenario.bizId = bizId; + bizScenario.useCase = useCase; + bizScenario.scenario = scenario; + return bizScenario; + } + + public static BizScenario valueOf(String bizId){ + return BizScenario.valueOf(bizId, DEFAULT_USE_CASE, DEFAULT_SCENARIO); + } + + public static BizScenario valueOf(String useCase, String scenario){ + return BizScenario.valueOf(DEFAULT_BIZ_ID, useCase, scenario); + } + + public static BizScenario newDefault(){ + return BizScenario.valueOf(DEFAULT_BIZ_ID, DEFAULT_USE_CASE, DEFAULT_SCENARIO); + } +} diff --git a/cola-framework-core/pom.xml b/cola-framework-core/pom.xml new file mode 100644 index 000000000..478c82c65 --- /dev/null +++ b/cola-framework-core/pom.xml @@ -0,0 +1,173 @@ + + + 4.0.0 + + com.aliyun + cola-core + jar + 3.0.0 + + Cola core + https://github.com/alibaba/COLA + Cola framework core components + + + + sonatype-nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + sonatype-nexus-staging + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + GNU Lesser General Public License v2.1 + https://github.com/alibaba/COLA/blob/master/LICENSE + repo + + + + + scm:git:https://github.com/alibaba/COLA.git + scm:git:https://github.com/alibaba/COLA.git + https://github.com/alibaba/COLA + + + + + Frank + Frank Zhang + 25216348@qq.com + + + + + 1.8 + 1.8 + 1.8 + UTF-8 + UTF-8 + + + + + com.aliyun + cola-common + 3.0.0 + + + + org.springframework + spring-core + 5.2.0.RELEASE + provided + + + org.springframework + spring-context + 5.2.0.RELEASE + provided + + + org.slf4j + slf4j-api + 1.7.9 + provided + + + junit + junit + 4.12 + test + + + org.springframework + spring-test + 4.3.2.RELEASE + test + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + verify + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + UTF-8 + none + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + sonatype-nexus-staging + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/boot/AbstractComponentExecutor.java b/cola-framework-core/src/main/java/com/alibaba/cola/boot/AbstractComponentExecutor.java new file mode 100644 index 000000000..2de3a9484 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/boot/AbstractComponentExecutor.java @@ -0,0 +1,52 @@ +package com.alibaba.cola.boot; + +import com.alibaba.cola.extension.BizScenario; +import com.alibaba.cola.extension.ExtensionCoordinate; + +import java.util.function.Consumer; +import java.util.function.Function; + +/** + * @author fulan.zjf + * @date 2017/12/21 + */ +public abstract class AbstractComponentExecutor { + + /** + * Execute extension with Response + * + * @param targetClz + * @param bizScenario + * @param exeFunction + * @param Response Type + * @param Parameter Type + * @return + */ + public R execute(Class targetClz, BizScenario bizScenario, Function exeFunction) { + T component = locateComponent(targetClz, bizScenario); + return exeFunction.apply(component); + } + + public R execute(ExtensionCoordinate extensionCoordinate, Function exeFunction){ + return execute((Class) extensionCoordinate.getExtensionPointClass(), extensionCoordinate.getBizScenario(), exeFunction); + } + + /** + * Execute extension without Response + * + * @param targetClz + * @param context + * @param exeFunction + * @param Parameter Type + */ + public void executeVoid(Class targetClz, BizScenario context, Consumer exeFunction) { + T component = locateComponent(targetClz, context); + exeFunction.accept(component); + } + + public void executeVoid(ExtensionCoordinate extensionCoordinate, Consumer exeFunction){ + executeVoid(extensionCoordinate.getExtensionPointClass(), extensionCoordinate.getBizScenario(), exeFunction); + } + + protected abstract C locateComponent(Class targetClz, BizScenario context); +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/boot/EventRegister.java b/cola-framework-core/src/main/java/com/alibaba/cola/boot/EventRegister.java new file mode 100644 index 000000000..951e4630f --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/boot/EventRegister.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.boot; + +import com.alibaba.cola.common.ApplicationContextHelper; +import com.alibaba.cola.common.ColaConstant; +import com.alibaba.cola.event.EventI; +import com.alibaba.cola.event.EventHandlerI; +import com.alibaba.cola.event.EventHub; +import com.alibaba.cola.exception.framework.ColaException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.lang.reflect.Method; + +/** + * EventRegister + * + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +@Component +public class EventRegister{ + + @Resource + private EventHub eventHub; + + private Class getEventFromExecutor(Class eventExecutorClz) { + Method[] methods = eventExecutorClz.getDeclaredMethods(); + for (Method method : methods) { + if (isExecuteMethod(method)){ + return checkAndGetEventParamType(method); + } + } + throw new ColaException("Event param in " + eventExecutorClz + " " + ColaConstant.EXE_METHOD + + "() is not detected"); + } + + public void doRegistration(EventHandlerI eventHandler){ + Class eventClz = getEventFromExecutor(eventHandler.getClass()); + eventHub.register(eventClz, eventHandler); + } + + private boolean isExecuteMethod(Method method){ + return ColaConstant.EXE_METHOD.equals(method.getName()) && !method.isBridge(); + } + + private Class checkAndGetEventParamType(Method method){ + Class[] exeParams = method.getParameterTypes(); + if (exeParams.length == 0){ + throw new ColaException("Execute method in "+method.getDeclaringClass()+" should at least have one parameter"); + } + if(!EventI.class.isAssignableFrom(exeParams[0]) ){ + throw new ColaException("Execute method in "+method.getDeclaringClass()+" should be the subClass of Event"); + } + return exeParams[0]; + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/boot/ExtensionRegister.java b/cola-framework-core/src/main/java/com/alibaba/cola/boot/ExtensionRegister.java new file mode 100644 index 000000000..7644e1507 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/boot/ExtensionRegister.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.boot; + +import com.alibaba.cola.common.ColaConstant; +import com.alibaba.cola.exception.framework.ColaException; +import com.alibaba.cola.extension.*; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * ExtensionRegister + * @author fulan.zjf 2017-11-05 + */ +@Component +public class ExtensionRegister{ + + @Resource + private ExtensionRepository extensionRepository; + + + public void doRegistration(ExtensionPointI extensionObject){ + Class extensionClz = extensionObject.getClass(); + Extension extensionAnn = extensionClz.getDeclaredAnnotation(Extension.class); + BizScenario bizScenario = BizScenario.valueOf(extensionAnn.bizId(), extensionAnn.useCase(), extensionAnn.scenario()); + ExtensionCoordinate extensionCoordinate = new ExtensionCoordinate(calculateExtensionPoint(extensionClz), bizScenario.getUniqueIdentity()); + ExtensionPointI preVal = extensionRepository.getExtensionRepo().put(extensionCoordinate, extensionObject); + if (preVal != null) { + throw new ColaException("Duplicate registration is not allowed for :" + extensionCoordinate); + } + + } + + /** + * @param targetClz + * @return + */ + private String calculateExtensionPoint(Class targetClz) { + Class[] interfaces = targetClz.getInterfaces(); + if (interfaces == null || interfaces.length == 0) + throw new ColaException("Please assign a extension point interface for "+targetClz); + for (Class intf : interfaces) { + String extensionPoint = intf.getSimpleName(); + if (extensionPoint.contains(ColaConstant.EXTENSION_EXTPT_NAMING)) + return intf.getName(); + } + throw new ColaException("Your name of ExtensionPoint for "+targetClz+" is not valid, must be end of "+ ColaConstant.EXTENSION_EXTPT_NAMING); + } + +} \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/boot/SpringBootstrap.java b/cola-framework-core/src/main/java/com/alibaba/cola/boot/SpringBootstrap.java new file mode 100644 index 000000000..cfe17e54e --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/boot/SpringBootstrap.java @@ -0,0 +1,39 @@ +package com.alibaba.cola.boot; + +import com.alibaba.cola.common.ApplicationContextHelper; +import com.alibaba.cola.event.EventHandler; +import com.alibaba.cola.event.EventHandlerI; +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.extension.ExtensionPointI; +import org.springframework.context.ApplicationContext; + +import javax.annotation.Resource; +import java.util.Map; + +/** + * SpringBootstrap + * + * @author Frank Zhang + * @date 2020-06-18 7:55 PM + */ +public class SpringBootstrap { + + @Resource + private ExtensionRegister extensionRegister; + + @Resource + private EventRegister eventRegister; + + public void init(){ + ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext(); + Map extensionBeans = applicationContext.getBeansWithAnnotation(Extension.class); + extensionBeans.values().forEach( + extension -> extensionRegister.doRegistration((ExtensionPointI) extension) + ); + + Map eventHandlerBeans = applicationContext.getBeansWithAnnotation(EventHandler.class); + eventHandlerBeans.values().forEach( + eventHandler -> eventRegister.doRegistration((EventHandlerI) eventHandler) + ); + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/boot/package-info.java b/cola-framework-core/src/main/java/com/alibaba/cola/boot/package-info.java new file mode 100644 index 000000000..296568603 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/boot/package-info.java @@ -0,0 +1,6 @@ +/** + * This package contains Bootstrap class of Application. + * + * @author fulan.zjf + */ +package com.alibaba.cola.boot; \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/common/ApplicationContextHelper.java b/cola-framework-core/src/main/java/com/alibaba/cola/common/ApplicationContextHelper.java new file mode 100644 index 000000000..ba8ec1ff5 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/common/ApplicationContextHelper.java @@ -0,0 +1,52 @@ +package com.alibaba.cola.common; + +import com.alibaba.cola.exception.framework.BasicErrorCode; +import com.alibaba.cola.exception.SysException; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * ApplicationContextHelper + * + * @author Frank Zhang + * @date 2018-01-07 12:30 PM + */ +@Component +public class ApplicationContextHelper implements ApplicationContextAware{ + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextHelper.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext(){ + return ApplicationContextHelper.applicationContext; + } + + public static T getBean(Class targetClz){ + T beanInstance = null; + //优先按type查 + try { + beanInstance = (T) applicationContext.getBean(targetClz); + }catch (Exception e){ + } + //按name查 + if(beanInstance == null){ + String simpleName = targetClz.getSimpleName(); + //首字母小写 + simpleName = Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1); + beanInstance = (T) applicationContext.getBean(simpleName); + } + if(beanInstance == null){ + new SysException(BasicErrorCode.COLA_ERROR, "Component " + targetClz + " can not be found in Spring Container"); + } + return beanInstance; + } + public static Object getBean(String claz){ + return ApplicationContextHelper.applicationContext.getBean(claz); + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/common/ColaConstant.java b/cola-framework-core/src/main/java/com/alibaba/cola/common/ColaConstant.java new file mode 100644 index 000000000..b268bb139 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/common/ColaConstant.java @@ -0,0 +1,20 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.common; + +/** + * CoreConstant + * @author fulan.zjf 2017-11-04 + */ +public class ColaConstant { + + public final static String DOT_SEPARATOR = "."; + public final static String EXTENSION_EXTPT_NAMING = "ExtPt"; + + public final static String EXE_METHOD = "execute"; +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainFactory.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainFactory.java new file mode 100644 index 000000000..b838616c6 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainFactory.java @@ -0,0 +1,20 @@ +package com.alibaba.cola.domain; + +import com.alibaba.cola.common.ApplicationContextHelper; + +/** + * DomainFactory + * + * @author Frank Zhang + * @date 2019-01-03 2:41 PM + */ +public class DomainFactory { + + public static T create(Class entityClz){ + return ApplicationContextHelper.getBean(entityClz); + } + + public static T getBean(Class entityClz){ + return ApplicationContextHelper.getBean(entityClz); + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainFactoryI.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainFactoryI.java new file mode 100644 index 000000000..ebe486dd3 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainFactoryI.java @@ -0,0 +1,12 @@ +package com.alibaba.cola.domain; + +/** + * 领域工厂 + * @author xueliang.sxl + * + */ +public interface DomainFactoryI { + + T create(); + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainServiceI.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainServiceI.java new file mode 100644 index 000000000..ed97d5c1a --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/DomainServiceI.java @@ -0,0 +1,10 @@ +package com.alibaba.cola.domain; + +/** + * 领域服务,继承自DomainServiceI的接口都认为是DomainAbility + * @author xueliang.sxl + * + */ +public interface DomainServiceI { + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/Entity.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/Entity.java new file mode 100644 index 000000000..da4799636 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/Entity.java @@ -0,0 +1,21 @@ +package com.alibaba.cola.domain; + +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import java.lang.annotation.*; + +/** + * Entity, Entity Object is prototype and is not thread-safe + * + * @author Frank Zhang + * @date 2019-01-03 2:53 PM + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public @interface Entity { +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/EntityObject.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/EntityObject.java new file mode 100755 index 000000000..9d0f1aa29 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/EntityObject.java @@ -0,0 +1,23 @@ +package com.alibaba.cola.domain; + + +import com.alibaba.cola.extension.BizScenario; +/** + * Entity Object + * + * This is the parent object of all domain objects + * @author fulan.zjf 2017年10月27日 上午10:16:10 + */ + +public abstract class EntityObject { + public BizScenario getBizScenario() { + return bizScenario; + } + + public void setBizScenario(BizScenario bizScenario) { + this.bizScenario = bizScenario; + } + + private BizScenario bizScenario; + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/ValueObject.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/ValueObject.java new file mode 100644 index 000000000..a031678e0 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/ValueObject.java @@ -0,0 +1,10 @@ +package com.alibaba.cola.domain; + +/** + * 领域值对象 + * @author xueliang.sxl + * + */ +public interface ValueObject { + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/domain/package-info.java b/cola-framework-core/src/main/java/com/alibaba/cola/domain/package-info.java new file mode 100644 index 000000000..0c5cd97ec --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/domain/package-info.java @@ -0,0 +1,6 @@ +/** + * 领域模型抽象层 + * + * @author fulan.zjf + */ +package com.alibaba.cola.domain; \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/event/EventBus.java b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventBus.java new file mode 100644 index 000000000..35baa1106 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventBus.java @@ -0,0 +1,104 @@ +package com.alibaba.cola.event; + +import com.alibaba.cola.dto.ErrorCodeI; +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.exception.framework.BaseException; +import com.alibaba.cola.exception.framework.BasicErrorCode; +import com.alibaba.cola.exception.framework.ColaException; +import com.alibaba.cola.logger.Logger; +import com.alibaba.cola.logger.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * Event Bus + * + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +@Component +public class EventBus implements EventBusI{ + Logger logger = LoggerFactory.getLogger(EventBus.class); + + /** + * 默认线程池 + * 如果处理器无定制线程池,则使用此默认 + */ + ExecutorService defaultExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() + 1, + Runtime.getRuntime().availableProcessors() + 1, + 0L,TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(1000)); + + @Autowired + private EventHub eventHub; + + @SuppressWarnings("unchecked") + @Override + public Response fire(EventI event) { + Response response = null; + EventHandlerI eventHandlerI = null; + try { + eventHandlerI = eventHub.getEventHandler(event.getClass()).get(0); + response = eventHandlerI.execute(event); + }catch (Exception exception) { + response = handleException(eventHandlerI, response, exception); + } + return response; + } + + @Override + public void fireAll(EventI event){ + eventHub.getEventHandler(event.getClass()).stream().map(p->{ + Response response = null; + try { + response = p.execute(event); + }catch (Exception exception) { + response = handleException(p, response, exception); + } + return response; + }).collect(Collectors.toList()); + } + + @Override + public void asyncFire(EventI event){ + eventHub.getEventHandler(event.getClass()).parallelStream().map(p->{ + Response response = null; + try { + if(null != p.getExecutor()){ + p.getExecutor().submit(()->p.execute(event)); + }else{ + defaultExecutor.submit(()->p.execute(event)); + } + }catch (Exception exception) { + response = handleException(p, response, exception); + } + return response; + }).collect(Collectors.toList()); + } + + private Response handleException(EventHandlerI handler, Response response, Exception exception) { + logger.error(exception.getMessage(), exception); + Class responseClz = eventHub.getResponseRepository().get(handler.getClass()); + try { + response = (Response) responseClz.newInstance(); + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new ColaException(e.getMessage()); + } + if (exception instanceof BaseException) { + ErrorCodeI errCode = ((BaseException) exception).getErrCode(); + response.setErrCode(errCode.getErrCode()); + } + else { + response.setErrCode(BasicErrorCode.SYS_ERROR.getErrCode()); + } + response.setErrMessage(exception.getMessage()); + return response; + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/event/EventBusI.java b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventBusI.java new file mode 100644 index 000000000..147cbfc5c --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventBusI.java @@ -0,0 +1,34 @@ +package com.alibaba.cola.event; + +import com.alibaba.cola.dto.Response; + + +/** + * EventBus interface + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +public interface EventBusI { + + /** + * Send event to EventBus + * + * @param event + * @return Response + */ + public Response fire(EventI event); + + /** + * fire all handlers which registed the event + * + * @param event + * @return Response + */ + public void fireAll(EventI event); + + /** + * Async fire all handlers + * @param event + */ + public void asyncFire(EventI event); +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHandler.java b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHandler.java new file mode 100644 index 000000000..f367d31d4 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHandler.java @@ -0,0 +1,16 @@ +package com.alibaba.cola.event; + +import org.springframework.stereotype.Component; + +import java.lang.annotation.*; + +/** + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Component +public @interface EventHandler { +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHandlerI.java b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHandlerI.java new file mode 100644 index 000000000..657249f60 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHandlerI.java @@ -0,0 +1,20 @@ +package com.alibaba.cola.event; + +import com.alibaba.cola.dto.Response; + +import java.util.concurrent.ExecutorService; + +/** + * event handler + * + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +public interface EventHandlerI { + + default public ExecutorService getExecutor(){ + return null; + } + + public R execute(E e); +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHub.java b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHub.java new file mode 100644 index 000000000..69744ab42 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/event/EventHub.java @@ -0,0 +1,66 @@ +package com.alibaba.cola.event; + +import com.alibaba.cola.exception.framework.ColaException; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 事件控制中枢 + * @author shawnzhan.zxy + * @date 2017/11/20 + */ +@SuppressWarnings("rawtypes") +@Component +public class EventHub { + + private HashMap> eventRepository = new HashMap<>(); + + private Map responseRepository = new HashMap<>(); + + public HashMap> getEventRepository() { + return eventRepository; + } + + public void setEventRepository(HashMap> eventRepository) { + this.eventRepository = eventRepository; + } + + public Map getResponseRepository() { + return responseRepository; + } + + public List getEventHandler(Class eventClass) { + List eventHandlerIList = findHandler(eventClass); + if (eventHandlerIList == null || eventHandlerIList.size() == 0) { + throw new ColaException(eventClass + "is not registered in eventHub, please register first"); + } + return eventHandlerIList; + } + + /** + * 注册事件 + * @param eventClz + * @param executor + */ + public void register(Class eventClz, EventHandlerI executor){ + List eventHandlers = eventRepository.get(eventClz); + if(eventHandlers == null){ + eventHandlers = new ArrayList<>(); + eventRepository.put(eventClz, eventHandlers); + } + eventHandlers.add(executor); + + } + + private List findHandler(Class eventClass){ + List eventHandlerIList = null; + Class cls = eventClass; + eventHandlerIList = eventRepository.get(cls); + return eventHandlerIList; + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/Assert.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/Assert.java new file mode 100644 index 000000000..4ad31e93c --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/Assert.java @@ -0,0 +1,92 @@ +package com.alibaba.cola.exception; + +import com.alibaba.cola.dto.ErrorCodeI; +import com.alibaba.cola.exception.framework.BasicErrorCode; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.Map; + +/** + * Assertion utility class that assists in validating arguments. + * + *

Useful for identifying programmer errors early and clearly at runtime. + * + *

For example, if the contract of a public method states it does not + * allow {@code null} arguments, {@code Assert} can be used to validate that + * contract. + * + * For example: + * + *

+ * Assert.notNull(clazz, "The class must not be null");
+ * Assert.isTrue(i > 0, "The value must be greater than zero");
+ * + * This class is empowered by {@link org.springframework.util.Assert} + * + * @author Frank Zhang + * @date 2019-01-13 11:49 AM + */ +public abstract class Assert { + + /** + * Assert a boolean expression, throwing {@code BizException} + * + * for example + * + *
Assert.isTrue(i != 0, errorCode.B_ORDER_illegalNumber, "The order number can not be zero");
+ * + * @param expression a boolean expression + * @param errorCode + * @param message the exception message to use if the assertion fails + * @throws BizException if expression is {@code false} + */ + public static void isTrue(boolean expression, ErrorCodeI errorCode, String message){ + if (!expression) { + throw new BizException(errorCode, message); + } + } + + public static void isTrue(boolean expression, String message) { + isTrue(expression, BasicErrorCode.BIZ_ERROR, message); + } + + public static void isTrue(boolean expression) { + isTrue(expression, "[Assertion failed] - this expression must be true"); + } + + public static void notNull(Object object, ErrorCodeI errorCode, String message) { + if (object == null) { + throw new BizException(errorCode, message); + } + } + + public static void notNull(Object object, String message) { + notNull(object, BasicErrorCode.BIZ_ERROR, message); + } + + public static void notNull(Object object){ + notNull(object, BasicErrorCode.BIZ_ERROR, "[Assertion failed] - the argument "+object+" must not be null"); + } + + public static void notEmpty(Collection collection) { + notEmpty(collection, + "[Assertion failed] - this collection must not be empty: it must contain at least 1 element"); + } + + public static void notEmpty(Collection collection, String message) { + if (CollectionUtils.isEmpty(collection)) { + throw new BizException(message); + } + } + + public static void notEmpty(Map map, String message) { + if (CollectionUtils.isEmpty(map)) { + throw new BizException(message); + } + } + + public static void notEmpty(Map map) { + notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry"); + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/BizException.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/BizException.java new file mode 100644 index 000000000..f9e5b0099 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/BizException.java @@ -0,0 +1,28 @@ +package com.alibaba.cola.exception; + +import com.alibaba.cola.dto.ErrorCodeI; +import com.alibaba.cola.exception.framework.BaseException; +import com.alibaba.cola.exception.framework.BasicErrorCode; + +/** + * BizException is known Exception, no need retry + */ +public class BizException extends BaseException { + + private static final long serialVersionUID = 1L; + + public BizException(String errMessage){ + super(errMessage); + this.setErrCode(BasicErrorCode.BIZ_ERROR); + } + + public BizException(ErrorCodeI errCode, String errMessage){ + super(errMessage); + this.setErrCode(errCode); + } + + public BizException(String errMessage, Throwable e) { + super(errMessage, e); + this.setErrCode(BasicErrorCode.BIZ_ERROR); + } +} \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/ExceptionHandlerI.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/ExceptionHandlerI.java new file mode 100644 index 000000000..3b68ed70b --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/ExceptionHandlerI.java @@ -0,0 +1,14 @@ +package com.alibaba.cola.exception; + +import com.alibaba.cola.dto.Command; +import com.alibaba.cola.dto.Response; + +/** + * ExceptionHandlerI provide a backdoor that Application can override the default Exception handling + * + * @author Frank Zhang + * @date 2019-01-02 11:25 PM + */ +public interface ExceptionHandlerI { + public void handleException(Command cmd, Response response, Exception exception); +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/SysException.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/SysException.java new file mode 100644 index 000000000..e3b0953b1 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/SysException.java @@ -0,0 +1,35 @@ +package com.alibaba.cola.exception; + +import com.alibaba.cola.dto.ErrorCodeI; +import com.alibaba.cola.exception.framework.BaseException; +import com.alibaba.cola.exception.framework.BasicErrorCode; + +/** + * System Exception is unexpected Exception, retry might work again + * + * @author Danny.Lee 2018/1/27 + */ +public class SysException extends BaseException { + + private static final long serialVersionUID = 4355163994767354840L; + + public SysException(String errMessage){ + super(errMessage); + this.setErrCode(BasicErrorCode.SYS_ERROR); + } + + public SysException(ErrorCodeI errCode, String errMessage) { + super(errMessage); + this.setErrCode(errCode); + } + + public SysException(String errMessage, Throwable e) { + super(errMessage, e); + this.setErrCode(BasicErrorCode.SYS_ERROR); + } + + public SysException(String errMessage, ErrorCodeI errorCode, Throwable e) { + super(errMessage, e); + this.setErrCode(errorCode); + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/BaseException.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/BaseException.java new file mode 100644 index 000000000..94cae8f33 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/BaseException.java @@ -0,0 +1,33 @@ +package com.alibaba.cola.exception.framework; + +import com.alibaba.cola.dto.ErrorCodeI; + +/** + * + * Base Exception is the parent of all exceptions + * + * @author fulan.zjf 2017年10月22日 上午12:00:39 + */ +public abstract class BaseException extends RuntimeException{ + + private static final long serialVersionUID = 1L; + + private ErrorCodeI errCode; + + public BaseException(String errMessage){ + super(errMessage); + } + + public BaseException(String errMessage, Throwable e) { + super(errMessage, e); + } + + public ErrorCodeI getErrCode() { + return errCode; + } + + public void setErrCode(ErrorCodeI errCode) { + this.errCode = errCode; + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/BasicErrorCode.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/BasicErrorCode.java new file mode 100644 index 000000000..f29fc05b9 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/BasicErrorCode.java @@ -0,0 +1,39 @@ +package com.alibaba.cola.exception.framework; + +import com.alibaba.cola.dto.ErrorCodeI; + +/** + * + * There are only 3 basic ErrorCode: + * COLA_ERROR + * BIZ_ERROR + * SYS_ERROR + * + * Created by fulan.zjf on 2017/12/18. + */ +public enum BasicErrorCode implements ErrorCodeI { + + BIZ_ERROR("BIZ_ERROR" , "通用的业务逻辑错误"), + + COLA_ERROR("COLA_FRAMEWORK_ERROR" , "COLA框架错误"), + + SYS_ERROR("SYS_ERROR" , "未知的系统错误" ); + + private String errCode; + private String errDesc; + + private BasicErrorCode(String errCode, String errDesc){ + this.errCode = errCode; + this.errDesc = errDesc; + } + + @Override + public String getErrCode() { + return errCode; + } + + @Override + public String getErrDesc() { + return errDesc; + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/ColaException.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/ColaException.java new file mode 100644 index 000000000..bab5be9ff --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/ColaException.java @@ -0,0 +1,22 @@ +package com.alibaba.cola.exception.framework; + +/** + * + * Infrastructure Exception + * + * @author fulan.zjf 2017年10月22日 下午5:56:57 + */ +public class ColaException extends BaseException { + + private static final long serialVersionUID = 1L; + + public ColaException(String errMessage){ + super(errMessage); + this.setErrCode(BasicErrorCode.COLA_ERROR); + } + + public ColaException(String errMessage, Throwable e) { + super(errMessage, e); + this.setErrCode(BasicErrorCode.COLA_ERROR); + } +} \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/DefaultExceptionHandler.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/DefaultExceptionHandler.java new file mode 100644 index 000000000..66856bfb9 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/DefaultExceptionHandler.java @@ -0,0 +1,56 @@ +package com.alibaba.cola.exception.framework; + +import com.alibaba.cola.dto.Command; +import com.alibaba.cola.dto.ErrorCodeI; +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.exception.ExceptionHandlerI; +import com.alibaba.cola.logger.Logger; +import com.alibaba.cola.logger.LoggerFactory; + +/** + * DefaultExceptionHandler + * + * @author Frank Zhang + * @date 2019-01-08 9:51 AM + */ +public class DefaultExceptionHandler implements ExceptionHandlerI { + + private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandler.class); + + public static DefaultExceptionHandler singleton = new DefaultExceptionHandler(); + + @Override + public void handleException(Command cmd, Response response, Exception exception) { + buildResponse(response, exception); + printLog(cmd, response, exception); + } + + private void printLog(Command cmd, Response response, Exception exception) { + if(exception instanceof BaseException){ + //biz exception is expected, only warn it + logger.warn(buildErrorMsg(cmd, response)); + } + else{ + //sys exception should be monitored, and pay attention to it + logger.error(buildErrorMsg(cmd, response), exception); + } + } + + private String buildErrorMsg(Command cmd, Response response) { + return "Process [" + cmd + "] failed, errorCode: " + + response.getErrCode() + " errorMsg:" + + response.getErrMessage(); + } + + private void buildResponse(Response response, Exception exception) { + if (exception instanceof BaseException) { + ErrorCodeI errCode = ((BaseException) exception).getErrCode(); + response.setErrCode(errCode.getErrCode()); + } + else { + response.setErrCode(BasicErrorCode.SYS_ERROR.getErrCode()); + } + response.setErrMessage(exception.getMessage()); + response.setSuccess(false); + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/ExceptionHandlerFactory.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/ExceptionHandlerFactory.java new file mode 100644 index 000000000..81d1d749f --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/framework/ExceptionHandlerFactory.java @@ -0,0 +1,24 @@ +package com.alibaba.cola.exception.framework; + +import com.alibaba.cola.common.ApplicationContextHelper; +import com.alibaba.cola.exception.ExceptionHandlerI; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; + +/** + * ExceptionHandlerFactory + * + * @author Frank Zhang + * @date 2019-01-08 9:51 AM + */ +public class ExceptionHandlerFactory { + + public static ExceptionHandlerI getExceptionHandler(){ + try { + return ApplicationContextHelper.getBean(ExceptionHandlerI.class); + } + catch (NoSuchBeanDefinitionException ex){ + return DefaultExceptionHandler.singleton; + } + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/exception/package-info.java b/cola-framework-core/src/main/java/com/alibaba/cola/exception/package-info.java new file mode 100644 index 000000000..1f8451e8b --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/exception/package-info.java @@ -0,0 +1,6 @@ +/** + * This package defines all kinds of Exceptions of Application. + * + * @author fulan.zjf + */ +package com.alibaba.cola.exception; \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/extension/Extension.java b/cola-framework-core/src/main/java/com/alibaba/cola/extension/Extension.java new file mode 100644 index 000000000..180dd1b8e --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/extension/Extension.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.extension; + +import com.alibaba.cola.common.ColaConstant; +import org.springframework.stereotype.Component; + +import java.lang.annotation.*; + +/** + * Extension + * @author fulan.zjf 2017-11-05 + */ +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Component +public @interface Extension { + String bizId() default BizScenario.DEFAULT_BIZ_ID; + String useCase() default BizScenario.DEFAULT_USE_CASE; + String scenario() default BizScenario.DEFAULT_SCENARIO; +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionCoordinate.java b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionCoordinate.java new file mode 100644 index 000000000..be2edde1a --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionCoordinate.java @@ -0,0 +1,81 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.extension; + +/** + * Extension Coordinate(扩展坐标) is used to uniquely position an Extension + * @author fulan.zjf 2017-11-05 + */ +public class ExtensionCoordinate { + + private String extensionPointName; + private String bizScenarioUniqueIdentity; + + + + //Wrapper + private Class extensionPointClass; + private BizScenario bizScenario; + + public Class getExtensionPointClass() { + return extensionPointClass; + } + + public BizScenario getBizScenario() { + return bizScenario; + } + + public static ExtensionCoordinate valueOf(Class extPtClass, BizScenario bizScenario){ + return new ExtensionCoordinate(extPtClass, bizScenario); + } + + public ExtensionCoordinate(Class extPtClass, BizScenario bizScenario){ + this.extensionPointClass = extPtClass; + this.extensionPointName = extPtClass.getName(); + this.bizScenario = bizScenario; + this.bizScenarioUniqueIdentity = bizScenario.getUniqueIdentity(); + } + + /** + * @param extensionPoint + * @param bizScenario + */ + public ExtensionCoordinate(String extensionPoint, String bizScenario){ + this.extensionPointName = extensionPoint; + this.bizScenarioUniqueIdentity = bizScenario; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bizScenarioUniqueIdentity == null) ? 0 : bizScenarioUniqueIdentity.hashCode()); + result = prime * result + ((extensionPointName == null) ? 0 : extensionPointName.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + ExtensionCoordinate other = (ExtensionCoordinate) obj; + if (bizScenarioUniqueIdentity == null) { + if (other.bizScenarioUniqueIdentity != null) return false; + } else if (!bizScenarioUniqueIdentity.equals(other.bizScenarioUniqueIdentity)) return false; + if (extensionPointName == null) { + if (other.extensionPointName != null) return false; + } else if (!extensionPointName.equals(other.extensionPointName)) return false; + return true; + } + + @Override + public String toString() { + return "ExtensionCoordinate [extensionPointName=" + extensionPointName + ", bizScenarioUniqueIdentity=" + bizScenarioUniqueIdentity + "]"; + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionExecutor.java b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionExecutor.java new file mode 100644 index 000000000..9953aa5ab --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionExecutor.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.extension; + +import com.alibaba.cola.boot.AbstractComponentExecutor; +import com.alibaba.cola.common.ColaConstant; +import com.alibaba.cola.exception.framework.ColaException; +import com.alibaba.cola.logger.Logger; +import com.alibaba.cola.logger.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * ExtensionExecutor + * @author fulan.zjf 2017-11-05 + */ +@Component +public class ExtensionExecutor extends AbstractComponentExecutor { + + private Logger logger = LoggerFactory.getLogger(ExtensionExecutor.class); + + @Autowired + private ExtensionRepository extensionRepository; + + @Override + protected C locateComponent(Class targetClz, BizScenario bizScenario) { + C extension = locateExtension(targetClz, bizScenario); + logger.debug("[Located Extension]: "+extension.getClass().getSimpleName()); + return extension; + } + + /** + * if the bizScenarioUniqueIdentity is "ali.tmall.supermarket" + * + * the search path is as below: + * 1、first try to get extension by "ali.tmall.supermarket", if get, return it. + * 2、loop try to get extension by "ali.tmall", if get, return it. + * 3、loop try to get extension by "ali", if get, return it. + * 4、if not found, try the default extension + * @param targetClz + */ + protected Ext locateExtension(Class targetClz, BizScenario bizScenario) { + checkNull(bizScenario); + + Ext extension; + String bizScenarioUniqueIdentity = bizScenario.getUniqueIdentity(); + logger.debug("BizScenario in locateExtension is : " + bizScenarioUniqueIdentity); + + // first try + extension = firstTry(targetClz, bizScenarioUniqueIdentity); + if (extension != null) { + return extension; + } + + // loop try + extension = loopTry(targetClz, bizScenarioUniqueIdentity); + if (extension != null) { + return extension; + } + + throw new ColaException("Can not find extension with ExtensionPoint: "+targetClz+" BizScenario:"+bizScenarioUniqueIdentity); + } + + private Ext firstTry(Class targetClz, String bizScenario) { + return (Ext)extensionRepository.getExtensionRepo().get(new ExtensionCoordinate(targetClz.getName(), bizScenario)); + } + + private Ext loopTry(Class targetClz, String bizScenario){ + Ext extension; + if (bizScenario == null){ + return null; + } + int lastDotIndex = bizScenario.lastIndexOf(ColaConstant.DOT_SEPARATOR); + while(lastDotIndex != -1){ + bizScenario = bizScenario.substring(0, lastDotIndex); + extension =(Ext)extensionRepository.getExtensionRepo().get(new ExtensionCoordinate(targetClz.getName(), bizScenario)); + if (extension != null) { + return extension; + } + lastDotIndex = bizScenario.lastIndexOf(ColaConstant.DOT_SEPARATOR); + } + return null; + } + + + private void checkNull(BizScenario bizScenario){ + if(bizScenario == null){ + throw new ColaException("BizScenario can not be null for extension"); + } + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionPointI.java b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionPointI.java new file mode 100644 index 000000000..1bd51a70d --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionPointI.java @@ -0,0 +1,10 @@ +package com.alibaba.cola.extension; + +/** + * ExtensionPointI is the parent interface of all ExtensionPoints + * 扩展点表示一块逻辑在不同的业务有不同的实现,使用扩展点做接口申明,然后用Extension(扩展)去实现扩展点。 + * @author fulan.zjf 2017-10-22 + */ +public interface ExtensionPointI { + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionRepository.java b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionRepository.java new file mode 100644 index 000000000..f53298dd7 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/extension/ExtensionRepository.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Alibaba.com All right reserved. This software is the + * confidential and proprietary information of Alibaba.com ("Confidential + * Information"). You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Alibaba.com. + */ +package com.alibaba.cola.extension; + +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * ExtensionRepository + * @author fulan.zjf 2017-11-05 + */ +@Component +public class ExtensionRepository { + + public Map getExtensionRepo() { + return extensionRepo; + } + + private Map extensionRepo = new HashMap<>(); + + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/extension/package-info.java b/cola-framework-core/src/main/java/com/alibaba/cola/extension/package-info.java new file mode 100644 index 000000000..0a93d236d --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/extension/package-info.java @@ -0,0 +1,6 @@ +/** + * Use {@link ExtensionPointI} to declare extension point, and use {@link Extension} Annotation to mark specific Extension. + * + * @author fulan.zjf + */ +package com.alibaba.cola.extension; \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/logger/Logger.java b/cola-framework-core/src/main/java/com/alibaba/cola/logger/Logger.java new file mode 100644 index 000000000..65f4b515d --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/logger/Logger.java @@ -0,0 +1,84 @@ +package com.alibaba.cola.logger; + +/** + * This is a typical DIP, by depending on ourselves logger, we can change the underline logger vendor easily + * + * @author fulan.zjf 2017年10月23日 下午11:58:54 + */ +public interface Logger { + + /** + * Log a message at the DEBUG level. + * + * @param msg the message string to be logged + */ + public void debug(String msg); + + /** + * Log a message at the DEBUG level. support format. + * + * @param msg + * @param args + */ + default public void debug(String msg, Object... args){ + debug(String.format(msg, args)); + } + + /** + * Log a message at the INFO level. + * + * @param msg the message string to be logged + */ + public void info(String msg); + + /** + * Log a message at the INFO level. support format. + * + * @param msg + * @param args + */ + default public void info(String msg, Object... args){ + info(String.format(msg, args)); + } + + /** + * Log a message at the WARN level. + * + * @param msg the message string to be logged + */ + public void warn(String msg); + + /** + * Log a message at the WARN level. support format. + * + * @param msg + * @param args + */ + default public void warn(String msg, Object... args){ + warn(String.format(msg, args)); + } + /** + * Log a message at the ERROR level. + * + * @param msg the message string to be logged + */ + public void error(String msg); + + /** + * Log a message at the ERROR level. support format. + * @param msg + * @param args + */ + default public void error(String msg, Object... args){ + error(String.format(msg, args)); + } + + /** + * Log an exception (throwable) at the ERROR level with an + * accompanying message. + * + * @param msg the message accompanying the exception + * @param t the exception (throwable) to log + */ + public void error(String msg, Throwable t); +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/logger/LoggerFactory.java b/cola-framework-core/src/main/java/com/alibaba/cola/logger/LoggerFactory.java new file mode 100644 index 000000000..a0f38d0ac --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/logger/LoggerFactory.java @@ -0,0 +1,32 @@ +package com.alibaba.cola.logger; + +public class LoggerFactory { + + private static boolean useSysLogger = false; + + public static Logger getLogger(Class clazz) { + if(useSysLogger) + return SysLogger.getLogger(clazz); + org.slf4j.Logger slfjLogger = org.slf4j.LoggerFactory.getLogger(clazz); + return new SLFJLogger(slfjLogger); + } + + public static Logger getLogger(String loggerName) { + if(useSysLogger) { + return SysLogger.getLogger(loggerName); + } + org.slf4j.Logger slfjLogger = org.slf4j.LoggerFactory.getLogger(loggerName); + return new SLFJLogger(slfjLogger); + } + + /** + * This is just for testing purpose, don't use it on product! + */ + public static void activateSysLogger() { + useSysLogger = true; + } + + public static void deactivateSysLogger() { + useSysLogger = false; + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/logger/SLFJLogger.java b/cola-framework-core/src/main/java/com/alibaba/cola/logger/SLFJLogger.java new file mode 100644 index 000000000..6748f1718 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/logger/SLFJLogger.java @@ -0,0 +1,39 @@ +package com.alibaba.cola.logger; + +public class SLFJLogger implements com.alibaba.cola.logger.Logger{ + + private org.slf4j.Logger slfjLogger; + + public SLFJLogger(org.slf4j.Logger slfjLogger) { + this.slfjLogger = slfjLogger; + } + + @Override + public void debug(String msg) { + slfjLogger.debug(msg); + } + + @Override + public void info(String msg) { + slfjLogger.info(msg); + + } + + @Override + public void warn(String msg) { + slfjLogger.warn(msg); + + } + + @Override + public void error(String msg) { + slfjLogger.error(msg); + + } + + @Override + public void error(String msg, Throwable t) { + slfjLogger.error(msg, t); + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/logger/SysLogger.java b/cola-framework-core/src/main/java/com/alibaba/cola/logger/SysLogger.java new file mode 100644 index 000000000..bdf70f906 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/logger/SysLogger.java @@ -0,0 +1,46 @@ +package com.alibaba.cola.logger; + +public class SysLogger implements Logger{ + + private String loggerName; + + private SysLogger(String loggerName){ + this.loggerName = loggerName; + } + + public static Logger getLogger(Class clz){ + return new SysLogger(clz.getName()); + } + + + public static Logger getLogger(String loggerName){ + return new SysLogger(loggerName); + } + + @Override + public void debug(String msg) { + System.out.println("["+loggerName+"] DEBUG: "+msg); + } + + @Override + public void info(String msg) { + System.out.println("["+loggerName+"] INFO: "+msg); + } + + @Override + public void warn(String msg) { + System.out.println("["+loggerName+"] WARN: "+msg); + } + + @Override + public void error(String msg) { + System.err.println("["+loggerName+"] ERROR: "+msg); + } + + @Override + public void error(String msg, Throwable t) { + System.err.println("["+loggerName+"] ERROR: "+msg); + t.printStackTrace(); + } + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/logger/package-info.java b/cola-framework-core/src/main/java/com/alibaba/cola/logger/package-info.java new file mode 100644 index 000000000..461ceb8f3 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/logger/package-info.java @@ -0,0 +1,6 @@ +/** + * CRM Logger is used to decouple and uniform logger usage with different vendors, typical DIP. + * + * @author fulan.zjf + */ +package com.alibaba.cola.logger; \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/Filter.java b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/Filter.java new file mode 100644 index 000000000..8d1338ee9 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/Filter.java @@ -0,0 +1,10 @@ +package com.alibaba.cola.pattern.filter; + +/** + * + */ +public interface Filter { + + void doFilter(T context, FilterInvoker nextFilter); + +} \ No newline at end of file diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterChain.java b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterChain.java new file mode 100644 index 000000000..01f0b3f55 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterChain.java @@ -0,0 +1,19 @@ +package com.alibaba.cola.pattern.filter; + +/** + * 拦截器链 + * @author shawnzhan.zxy + * @date 2018/04/17 + */ +public class FilterChain{ + + private FilterInvoker header; + + public void doFilter(T context){ + header.invoke(context); + } + + public void setHeader(FilterInvoker header) { + this.header = header; + } +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterChainFactory.java b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterChainFactory.java new file mode 100644 index 000000000..86e688253 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterChainFactory.java @@ -0,0 +1,30 @@ +package com.alibaba.cola.pattern.filter; + +import com.alibaba.cola.common.ApplicationContextHelper; + +/** + * 责任链模式工厂 + * @author shawnzhan.zxy + * @date 2018/04/17 + */ +public class FilterChainFactory { + + public static FilterChain buildFilterChain(Class... filterClsList) { + FilterInvoker last = new FilterInvoker(){}; + FilterChain filterChain = new FilterChain(); + for(int i = filterClsList.length - 1; i >= 0; i--){ + FilterInvoker next = last; + Filter filter = (Filter)ApplicationContextHelper.getBean(filterClsList[i]); + last = new FilterInvoker(){ + @Override + public void invoke(T context) { + filter.doFilter(context, next); + } + }; + } + filterChain.setHeader(last); + return filterChain; + } + + +} diff --git a/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterInvoker.java b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterInvoker.java new file mode 100644 index 000000000..4eecd4039 --- /dev/null +++ b/cola-framework-core/src/main/java/com/alibaba/cola/pattern/filter/FilterInvoker.java @@ -0,0 +1,10 @@ +package com.alibaba.cola.pattern.filter; + +/** + * @author shawnzhan.zxy + * @date 2018/04/17 + */ +public interface FilterInvoker { + + default public void invoke(T context){}; +} diff --git a/cola-framework-core/src/main/resources/sample.properties b/cola-framework-core/src/main/resources/sample.properties new file mode 100644 index 000000000..e69de29bb diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/SysLoggerPostProcessor.java b/cola-framework-core/src/test/java/com/alibaba/cola/SysLoggerPostProcessor.java new file mode 100644 index 000000000..11bb9d87f --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/SysLoggerPostProcessor.java @@ -0,0 +1,21 @@ +package com.alibaba.cola; + +import com.alibaba.cola.logger.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.stereotype.Component; + +/** + * SysLoggerPostProcessor + * + * @author Frank Zhang + * @date 2018-08-19 2:42 PM + */ +@Component +public class SysLoggerPostProcessor implements BeanFactoryPostProcessor { + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + LoggerFactory.activateSysLogger(); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/TestSpringConfig.java b/cola-framework-core/src/test/java/com/alibaba/cola/TestSpringConfig.java new file mode 100644 index 000000000..55a680eaa --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/TestSpringConfig.java @@ -0,0 +1,26 @@ +package com.alibaba.cola; + +import com.alibaba.cola.boot.SpringBootstrap; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * TestSpringConfig + * + * @author Frank Zhang + * @date 2020-06-18 8:03 PM + */ +@Configuration +@ComponentScan(value = {"com.alibaba.cola","com.alibaba.cola.test"}) +@PropertySource(value = {"/sample.properties"}) +public class TestSpringConfig { + + @Bean(initMethod = "init") + public SpringBootstrap bootstrap() { + SpringBootstrap bootstrap = new SpringBootstrap(); + return bootstrap; + } + +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/CustomerCommandTest.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/CustomerCommandTest.java new file mode 100644 index 000000000..2add17142 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/CustomerCommandTest.java @@ -0,0 +1,126 @@ +package com.alibaba.cola.test; + +import com.alibaba.cola.TestSpringConfig; +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.exception.BizException; +import com.alibaba.cola.extension.BizScenario; +import com.alibaba.cola.test.customer.*; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * CustomerCommandTest + * + * @author Frank Zhang 2018-01-06 7:55 PM + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = {TestSpringConfig.class}) +public class CustomerCommandTest { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Autowired + private CustomerServiceI customerService; + + @Value("${bizScenarioUniqueIdentity}") + private String bizCode; + + @Before + public void setUp() { + } + + @Test + public void testBizOneAddCustomerSuccess(){ + //1. Prepare + AddCustomerCmd addCustomerCmd = new AddCustomerCmd(); + CustomerCO customerCO = new CustomerCO(); + customerCO.setCompanyName("alibaba"); + customerCO.setSource(Constants.SOURCE_RFQ); + customerCO.setCustomerType(CustomerType.IMPORTANT); + addCustomerCmd.setCustomerCO(customerCO); + BizScenario scenario = BizScenario.valueOf(Constants.BIZ_1); + addCustomerCmd.setBizScenario(scenario); + + //2. Execute + Response response = customerService.addCustomer(addCustomerCmd); + + //3. Expect Success + Assert.assertTrue(response.isSuccess()); + } + + @Test(expected = BizException.class) + public void testBizOneAddCustomerFailure(){ + //1. Prepare + AddCustomerCmd addCustomerCmd = new AddCustomerCmd(); + CustomerCO customerCO = new CustomerCO(); + customerCO.setCompanyName("alibaba"); + customerCO.setSource(Constants.SOURCE_AD); + addCustomerCmd.setCustomerCO(customerCO); + BizScenario scenario = BizScenario.valueOf(Constants.BIZ_2); + addCustomerCmd.setBizScenario(scenario); + + //2. Execute + Response response = customerService.addCustomer(addCustomerCmd); + + //3. Expect exception + + } + + @Test + public void testBizTwoAddCustomer(){ + //1. Prepare + AddCustomerCmd addCustomerCmd = new AddCustomerCmd(); + CustomerCO customerCO = new CustomerCO(); + customerCO.setCompanyName("alibaba"); + customerCO.setSource(Constants.SOURCE_AD); + customerCO.setCustomerType(CustomerType.IMPORTANT); + addCustomerCmd.setCustomerCO(customerCO); + BizScenario scenario = BizScenario.valueOf(Constants.BIZ_2); + addCustomerCmd.setBizScenario(scenario); + //2. Execute + Response response = customerService.addCustomer(addCustomerCmd); + + //3. Expect Success + Assert.assertTrue(response.isSuccess()); + } + + /* @Test + public void testCompanyTypeViolation(){ + AddCustomerCmd addCustomerCmd = new AddCustomerCmd(); + CustomerCO customerCO = new CustomerCO(); + customerCO.setCompanyName("alibaba"); + customerCO.setSource(SourceType.AD.name()); + customerCO.setCustomerType(CustomerType.VIP); + addCustomerCmd.setCustomerCO(customerCO); + BizScenario scenario = BizScenario.valueOf(Constants.BIZ_1); + addCustomerCmd.setBizScenario(scenario); + Response response = customerService.addCustomer(addCustomerCmd); + + //Expect biz exception + Assert.assertFalse(response.isSuccess()); + Assert.assertEquals(response.getErrCode(), BasicErrorCode.BIZ_ERROR.getErrCode()); + } + */ + + +/* @Test + public void testParamValidationFail(){ + AddCustomerCmd addCustomerCmd = new AddCustomerCmd(); + BizScenario scenario = BizScenario.valueOf(Constants.BIZ_1); + addCustomerCmd.setBizScenario(scenario); + Response response = customerService.addCustomer(addCustomerCmd); + + //Expect parameter validation error + Assert.assertFalse(response.isSuccess()); + Assert.assertEquals(response.getErrCode(), BasicErrorCode.BIZ_ERROR.getErrCode()); + }*/ +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/EntityPrototypeTest.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/EntityPrototypeTest.java new file mode 100644 index 000000000..88a5670fd --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/EntityPrototypeTest.java @@ -0,0 +1,32 @@ +package com.alibaba.cola.test; + +import com.alibaba.cola.TestSpringConfig; +import com.alibaba.cola.common.ApplicationContextHelper; +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * EntityPrototypeTest + * + * @author Frank Zhang + * @date 2018-01-07 12:34 PM + */ + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = {TestSpringConfig.class}) +public class EntityPrototypeTest { + + @Test + public void testPrototype(){ + CustomerEntity customerEntity1 = (CustomerEntity)ApplicationContextHelper.getBean(CustomerEntity.class); + System.out.println(customerEntity1); + CustomerEntity customerEntity2 = (CustomerEntity)ApplicationContextHelper.getBean(CustomerEntity.class); + System.out.println(customerEntity2); + + Assert.assertFalse(customerEntity1 == customerEntity2); //It should be different objects + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/SpringConfigTest.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/SpringConfigTest.java new file mode 100644 index 000000000..347befe8c --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/SpringConfigTest.java @@ -0,0 +1,21 @@ +package com.alibaba.cola.test; + +import com.alibaba.cola.TestSpringConfig; +import com.alibaba.cola.boot.SpringBootstrap; +import com.alibaba.cola.logger.LoggerFactory; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +/** + * SpringConfigTest + * + * @author Frank Zhang + * @date 2020-06-18 8:09 PM + */ +public class SpringConfigTest { + public static void main(String[] args) { + LoggerFactory.activateSysLogger(); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestSpringConfig.class); + SpringBootstrap bootstrap = (SpringBootstrap)context.getBean("bootstrap"); + System.out.println(bootstrap); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/AddCustomerCmd.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/AddCustomerCmd.java new file mode 100644 index 000000000..3461c5015 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/AddCustomerCmd.java @@ -0,0 +1,25 @@ +package com.alibaba.cola.test.customer; + + +import com.alibaba.cola.dto.Command; + +/** + * AddCustomerCmd + * + * @author Frank Zhang 2018-01-06 7:28 PM + */ +public class AddCustomerCmd extends Command { + + + public CustomerCO getCustomerCO() { + return customerCO; + } + + public void setCustomerCO(CustomerCO customerCO) { + this.customerCO = customerCO; + } + + private CustomerCO customerCO; + + +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/AddCustomerCmdExe.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/AddCustomerCmdExe.java new file mode 100644 index 000000000..fac1875ca --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/AddCustomerCmdExe.java @@ -0,0 +1,48 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.extension.ExtensionExecutor; +import com.alibaba.cola.logger.Logger; +import com.alibaba.cola.logger.LoggerFactory; +import com.alibaba.cola.test.customer.convertor.CustomerConvertorExtPt; +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import com.alibaba.cola.test.customer.validator.extensionpoint.AddCustomerValidatorExtPt; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * AddCustomerCmdExe + * + * @author Frank Zhang 2018-01-06 7:48 PM + */ +@Component +public class AddCustomerCmdExe { + + private Logger logger = LoggerFactory.getLogger(AddCustomerCmd.class); + + @Resource + private ExtensionExecutor extensionExecutor; + + @Resource + private DomainEventPublisher domainEventPublisher; + + + public Response execute(AddCustomerCmd cmd) { + logger.info("Start processing command:" + cmd); + + //validation + extensionExecutor.executeVoid(AddCustomerValidatorExtPt.class, cmd.getBizScenario(), extension -> extension.validate(cmd)); + + //Convert CO to Entity + CustomerEntity customerEntity = extensionExecutor.execute(CustomerConvertorExtPt.class, cmd.getBizScenario(), extension -> extension.clientToEntity(cmd)); + + //Call Domain Entity for business logic processing + logger.info("Call Domain Entity for business logic processing..."+customerEntity); + customerEntity.addNewCustomer(); + + domainEventPublisher.publish(new CustomerCreatedEvent()); + logger.info("End processing command:" + cmd); + return Response.buildSuccess(); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/Constants.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/Constants.java new file mode 100644 index 000000000..900daf966 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/Constants.java @@ -0,0 +1,22 @@ +package com.alibaba.cola.test.customer; + +/** + * Constants + * + * @author Frank Zhang + * @date 2018-01-07 1:23 AM + */ +public class Constants { + + public static final String BIZ_1 = "BIZ_ONE"; + public static final String BIZ_2 = "BIZ_TWO"; + + public static final String TENANT_ID = "122344"; + + + public static final String SOURCE_AD = "Advertisement"; + public static final String SOURCE_WB = "Web site"; + public static final String SOURCE_RFQ = "Request For Quota"; + public static final String SOURCE_MARKETING = "Marketing"; + public static final String SOURCE_OFFLINE = "Off Line"; +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCO.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCO.java new file mode 100644 index 000000000..d80cbe437 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCO.java @@ -0,0 +1,40 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.ClientObject; + + +/** + * CustomerCO + * + * @author Frank Zhang 2018-01-06 7:30 PM + */ +public class CustomerCO extends ClientObject{ + + private String companyName; + private String source; //advertisement, p4p, RFQ, ATM + private CustomerType customerType; //potential, intentional, important, vip + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public CustomerType getCustomerType() { + return customerType; + } + + public void setCustomerType(CustomerType customerType) { + this.customerType = customerType; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCreatedEvent.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCreatedEvent.java new file mode 100644 index 000000000..9ef3b9e93 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCreatedEvent.java @@ -0,0 +1,12 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.event.DomainEventI; + +/** + * CustomerCreatedEvent + * + * @author Frank Zhang + * @date 2020-06-22 6:59 PM + */ +public class CustomerCreatedEvent implements DomainEventI { +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCreatedEventHandler.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCreatedEventHandler.java new file mode 100644 index 000000000..7269251c7 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerCreatedEventHandler.java @@ -0,0 +1,22 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.event.EventHandler; +import com.alibaba.cola.event.EventHandlerI; +import com.alibaba.cola.event.EventI; + +/** + * CustomerCreatedEventHandler + * + * @author Frank Zhang + * @date 2020-06-22 7:00 PM + */ +@EventHandler +public class CustomerCreatedEventHandler implements EventHandlerI { + + @Override + public Response execute(CustomerCreatedEvent customerCreatedEvent) { + System.out.println("customerCreatedEvent processed"); + return null; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerDO.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerDO.java new file mode 100644 index 000000000..2b79c3283 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerDO.java @@ -0,0 +1,65 @@ +package com.alibaba.cola.test.customer; + +/** + * CustomerDO + * + * @author Frank Zhang + * @date 2018-01-08 1:45 PM + */ + +public class CustomerDO implements java.io.Serializable { + private String customerId; + private String memberId; + private String globalId; + private String companyName; + private String source; + private String companyType; + + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(String customerId) { + this.customerId = customerId; + } + + public String getMemberId() { + return memberId; + } + + public void setMemberId(String memberId) { + this.memberId = memberId; + } + + public String getGlobalId() { + return globalId; + } + + public void setGlobalId(String globalId) { + this.globalId = globalId; + } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getCompanyType() { + return companyType; + } + + public void setCompanyType(String companyType) { + this.companyType = companyType; + } +} \ No newline at end of file diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerServiceI.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerServiceI.java new file mode 100644 index 000000000..313cd1dff --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerServiceI.java @@ -0,0 +1,14 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.dto.SingleResponse; + +/** + * CustomerServiceI + * + * @author Frank Zhang 2018-01-06 7:24 PM + */ +public interface CustomerServiceI { + public Response addCustomer(AddCustomerCmd addCustomerCmd); + public SingleResponse getCustomer(GetOneCustomerQry getOneCustomerQry); +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerServiceImpl.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerServiceImpl.java new file mode 100644 index 000000000..b3a1f9f79 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerServiceImpl.java @@ -0,0 +1,33 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.Response; +import com.alibaba.cola.dto.SingleResponse; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * CustomerServiceImpl + * + * @author Frank Zhang 2018-01-06 7:40 PM + */ +@Service +public class CustomerServiceImpl implements CustomerServiceI{ + + @Resource + private AddCustomerCmdExe addCustomerCmdExe; + + @Resource + private GetOneCustomerQryExe getOneCustomerQryExe; + + + @Override + public Response addCustomer(AddCustomerCmd addCustomerCmd) { + return addCustomerCmdExe.execute(addCustomerCmd); + } + + @Override + public SingleResponse getCustomer(GetOneCustomerQry getOneCustomerQry) { + return getOneCustomerQryExe.execute(getOneCustomerQry); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerType.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerType.java new file mode 100644 index 000000000..67f0669e4 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/CustomerType.java @@ -0,0 +1,13 @@ +package com.alibaba.cola.test.customer; + +/** + * CustomerType + * + * @author Frank Zhang 2018-01-06 7:35 PM + */ +public enum CustomerType { + POTENTIAL, + INTENTIONAL, + IMPORTANT, + VIP; +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/DomainEventPublisher.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/DomainEventPublisher.java new file mode 100644 index 000000000..992699c3d --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/DomainEventPublisher.java @@ -0,0 +1,23 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.event.DomainEventI; +import com.alibaba.cola.event.EventBusI; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * DomainEventPublisher + * + * @author Frank Zhang + * @date 2020-06-22 7:04 PM + */ +@Component +public class DomainEventPublisher { + @Resource + private EventBusI eventBus; + + public void publish(DomainEventI domainEvent) { + eventBus.fire(domainEvent); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/GetOneCustomerQry.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/GetOneCustomerQry.java new file mode 100644 index 000000000..9eab312d3 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/GetOneCustomerQry.java @@ -0,0 +1,29 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.Query; + +/** + * GetOneCustomerQry + * + * @author Frank Zhang 2018-01-06 7:38 PM + */ +public class GetOneCustomerQry extends Query{ + private long customerId; + private String companyName; + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/GetOneCustomerQryExe.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/GetOneCustomerQryExe.java new file mode 100644 index 000000000..18223008f --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/GetOneCustomerQryExe.java @@ -0,0 +1,18 @@ +package com.alibaba.cola.test.customer; + +import com.alibaba.cola.dto.SingleResponse; +import org.springframework.stereotype.Component; + +/** + * GetOneCustomerQryExe + * + * @author Frank Zhang + * @date 2020-06-22 5:12 PM + */ +@Component +public class GetOneCustomerQryExe { + + public SingleResponse execute(GetOneCustomerQry getOneCustomerQry){ + return null; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerBizOneConvertorExt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerBizOneConvertorExt.java new file mode 100644 index 000000000..5371cd8c7 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerBizOneConvertorExt.java @@ -0,0 +1,37 @@ +package com.alibaba.cola.test.customer.convertor; + +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.Constants; +import com.alibaba.cola.test.customer.CustomerCO; +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import com.alibaba.cola.test.customer.entity.SourceType; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * CustomerBizOneConvertorExt + * + * @author Frank Zhang + * @date 2018-01-07 3:05 AM + */ +@Extension(bizId = Constants.BIZ_1) +public class CustomerBizOneConvertorExt implements CustomerConvertorExtPt{ + + @Autowired + private CustomerConvertor customerConvertor;//Composite basic convertor to do basic conversion + + @Override + public CustomerEntity clientToEntity(AddCustomerCmd addCustomerCmd){ + CustomerEntity customerEntity = customerConvertor.clientToEntity(addCustomerCmd); + CustomerCO customerCO=addCustomerCmd.getCustomerCO(); + //In this business, AD and RFQ are regarded as different source + if(Constants.SOURCE_AD.equals(customerCO.getSource())) + { + customerEntity.setSourceType(SourceType.AD); + } + if (Constants.SOURCE_RFQ.equals(customerCO.getSource())){ + customerEntity.setSourceType(SourceType.RFQ); + } + return customerEntity; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerBizTwoConvertorExt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerBizTwoConvertorExt.java new file mode 100644 index 000000000..3fe87ccbe --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerBizTwoConvertorExt.java @@ -0,0 +1,33 @@ +package com.alibaba.cola.test.customer.convertor; + +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.Constants; +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import com.alibaba.cola.test.customer.entity.SourceType; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * CustomerBizTwoConvertorExt + * + * @author Frank Zhang + * @date 2018-01-07 3:05 AM + */ +@Extension(bizId = Constants.BIZ_2) +public class CustomerBizTwoConvertorExt implements CustomerConvertorExtPt{ + + @Autowired + private CustomerConvertor customerConvertor;//Composite basic convertor to do basic conversion + + @Override + public CustomerEntity clientToEntity(AddCustomerCmd addCustomerCmd){ + CustomerEntity customerEntity = customerConvertor.clientToEntity(addCustomerCmd); + //In this business, if customers from RFQ and Advertisement are both regarded as Advertisement + if(Constants.SOURCE_AD.equals(addCustomerCmd.getCustomerCO().getSource()) || Constants.SOURCE_RFQ.equals(addCustomerCmd.getCustomerCO().getSource())) + { + customerEntity.setSourceType(SourceType.AD); + } + return customerEntity; + } + +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerConvertor.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerConvertor.java new file mode 100644 index 000000000..01c7b7473 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerConvertor.java @@ -0,0 +1,27 @@ +package com.alibaba.cola.test.customer.convertor; + +import com.alibaba.cola.common.ApplicationContextHelper; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.CustomerCO; +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import org.springframework.stereotype.Component; + +/** + * CustomerConvertor + * + * @author Frank Zhang + * @date 2018-01-07 3:08 AM + */ +@Component +public class CustomerConvertor{ + + public CustomerEntity clientToEntity(Object clientObject){ + AddCustomerCmd addCustomerCmd = (AddCustomerCmd)clientObject; + CustomerCO customerCO=addCustomerCmd.getCustomerCO(); + CustomerEntity customerEntity = (CustomerEntity)ApplicationContextHelper.getBean(CustomerEntity.class); + customerEntity.setCompanyName(customerCO.getCompanyName()); + customerEntity.setCustomerType(customerCO.getCustomerType()); + customerEntity.setBizScenario(addCustomerCmd.getBizScenario()); + return customerEntity; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerConvertorExtPt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerConvertorExtPt.java new file mode 100644 index 000000000..2de901d0e --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/convertor/CustomerConvertorExtPt.java @@ -0,0 +1,16 @@ +package com.alibaba.cola.test.customer.convertor; + +import com.alibaba.cola.extension.ExtensionPointI; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.entity.CustomerEntity; + +/** + * CustomerConvertorExtPt + * + * @author Frank Zhang + * @date 2018-01-07 2:37 AM + */ +public interface CustomerConvertorExtPt extends ExtensionPointI { + + public CustomerEntity clientToEntity(AddCustomerCmd addCustomerCmd); +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/CustomerEntity.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/CustomerEntity.java new file mode 100644 index 000000000..1c0fd80a4 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/CustomerEntity.java @@ -0,0 +1,65 @@ +package com.alibaba.cola.test.customer.entity; + +import com.alibaba.cola.domain.Entity; +import com.alibaba.cola.domain.EntityObject; +import com.alibaba.cola.extension.ExtensionExecutor; +import com.alibaba.cola.test.customer.CustomerType; +import com.alibaba.cola.test.customer.entity.rule.CustomerRuleExtPt; +import com.alibaba.cola.test.customer.repository.CustomerRepository; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * Customer Entity + * + * @author Frank Zhang + * @date 2018-01-07 2:38 AM + */ +@Entity +public class CustomerEntity extends EntityObject { + + private String companyName; + private SourceType sourceType; + private CustomerType customerType; + + @Autowired + private CustomerRepository customerRepository; + @Autowired + private ExtensionExecutor extensionExecutor; + + public CustomerEntity() { + + } + + public void addNewCustomer() { + //Add customer policy + extensionExecutor.execute(CustomerRuleExtPt.class,this.getBizScenario(), extension -> extension.addCustomerCheck(this)); + + //Persist customer + customerRepository.persist(this); + + } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } + + public SourceType getSourceType() { + return sourceType; + } + + public void setSourceType(SourceType sourceType) { + this.sourceType = sourceType; + } + + public CustomerType getCustomerType() { + return customerType; + } + + public void setCustomerType(CustomerType customerType) { + this.customerType = customerType; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/SourceType.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/SourceType.java new file mode 100644 index 000000000..8b4062dfb --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/SourceType.java @@ -0,0 +1,13 @@ +package com.alibaba.cola.test.customer.entity; + +/** + * SourceType + * + * @author Frank Zhang + * @date 2018-01-07 3:02 AM + */ +public enum SourceType { + AD, //Advertisement 广告 + WB, // Web site 网站 + RFQ; // Request For Quota 询盘 +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerBizOneRuleExt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerBizOneRuleExt.java new file mode 100644 index 000000000..74ce15b2e --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerBizOneRuleExt.java @@ -0,0 +1,25 @@ +package com.alibaba.cola.test.customer.entity.rule; + +import com.alibaba.cola.exception.BizException; +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.test.customer.Constants; +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import com.alibaba.cola.test.customer.entity.SourceType; + +/** + * CustomerBizOneRuleExt + * + * @author Frank Zhang + * @date 2018-01-07 12:10 PM + */ +@Extension(bizId = Constants.BIZ_1) +public class CustomerBizOneRuleExt implements CustomerRuleExtPt{ + + @Override + public boolean addCustomerCheck(CustomerEntity customerEntity) { + if(SourceType.AD == customerEntity.getSourceType()){ + throw new BizException("Sorry, Customer from advertisement can not be added in this period"); + } + return true; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerBizTwoRuleExt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerBizTwoRuleExt.java new file mode 100644 index 000000000..653a3c7a0 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerBizTwoRuleExt.java @@ -0,0 +1,21 @@ +package com.alibaba.cola.test.customer.entity.rule; + +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.test.customer.Constants; +import com.alibaba.cola.test.customer.entity.CustomerEntity; + +/** + * CustomerBizTwoRuleExt + * + * @author Frank Zhang + * @date 2018-01-07 12:10 PM + */ +@Extension(bizId = Constants.BIZ_2) +public class CustomerBizTwoRuleExt implements CustomerRuleExtPt{ + + @Override + public boolean addCustomerCheck(CustomerEntity customerEntity) { + //Any Customer can be added + return true; + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerRuleExtPt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerRuleExtPt.java new file mode 100644 index 000000000..5cc01cf49 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/entity/rule/CustomerRuleExtPt.java @@ -0,0 +1,21 @@ +package com.alibaba.cola.test.customer.entity.rule; + +import com.alibaba.cola.extension.ExtensionPointI; +import com.alibaba.cola.test.customer.entity.CustomerEntity; + +/** + * CustomerRuleExtPt + * + * @author Frank Zhang + * @date 2018-01-07 12:03 PM + */ +public interface CustomerRuleExtPt extends ExtensionPointI{ + + //Different business check for different biz + public boolean addCustomerCheck(CustomerEntity customerEntity); + + //Different upgrade policy for different biz + default public void customerUpgradePolicy(CustomerEntity customerEntity){ + //Nothing special + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/repository/CustomerRepository.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/repository/CustomerRepository.java new file mode 100644 index 000000000..c0a980824 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/repository/CustomerRepository.java @@ -0,0 +1,18 @@ +package com.alibaba.cola.test.customer.repository; + +import com.alibaba.cola.test.customer.entity.CustomerEntity; +import org.springframework.stereotype.Repository; + +/** + * CustomerRepository + * + * @author Frank Zhang + * @date 2018-01-07 11:59 AM + */ +@Repository +public class CustomerRepository { + + public void persist(CustomerEntity customerEntity){ + System.out.println("Persist customer to DB : "+ customerEntity); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extension/AddCustomerBizOneValidator.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extension/AddCustomerBizOneValidator.java new file mode 100644 index 000000000..b784fa4ea --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extension/AddCustomerBizOneValidator.java @@ -0,0 +1,24 @@ +package com.alibaba.cola.test.customer.validator.extension; + +import com.alibaba.cola.exception.BizException; +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.Constants; +import com.alibaba.cola.test.customer.CustomerType; +import com.alibaba.cola.test.customer.validator.extensionpoint.AddCustomerValidatorExtPt; + +/** + * AddCustomerBizOneValidator + * + * @author Frank Zhang + * @date 2018-01-07 1:31 AM + */ +@Extension(bizId = Constants.BIZ_1) +public class AddCustomerBizOneValidator implements AddCustomerValidatorExtPt{ + + public void validate(AddCustomerCmd addCustomerCmd) { + //For BIZ TWO CustomerTYpe could not be VIP + if(CustomerType.VIP == addCustomerCmd.getCustomerCO().getCustomerType()) + throw new BizException("Customer Type could not be VIP for Biz One"); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extension/AddCustomerBizTwoValidator.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extension/AddCustomerBizTwoValidator.java new file mode 100644 index 000000000..320660515 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extension/AddCustomerBizTwoValidator.java @@ -0,0 +1,23 @@ +package com.alibaba.cola.test.customer.validator.extension; + +import com.alibaba.cola.exception.BizException; +import com.alibaba.cola.extension.Extension; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.Constants; +import com.alibaba.cola.test.customer.validator.extensionpoint.AddCustomerValidatorExtPt; + +/** + * AddCustomerBizTwoValidator + * + * @author Frank Zhang + * @date 2018-01-07 1:31 AM + */ +@Extension(bizId = Constants.BIZ_2) +public class AddCustomerBizTwoValidator implements AddCustomerValidatorExtPt{ + + public void validate(AddCustomerCmd addCustomerCmd) { + //For BIZ TWO CustomerTYpe could not be null + if (addCustomerCmd.getCustomerCO().getCustomerType() == null) + throw new BizException("CustomerType could not be null"); + } +} diff --git a/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extensionpoint/AddCustomerValidatorExtPt.java b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extensionpoint/AddCustomerValidatorExtPt.java new file mode 100644 index 000000000..0a5637353 --- /dev/null +++ b/cola-framework-core/src/test/java/com/alibaba/cola/test/customer/validator/extensionpoint/AddCustomerValidatorExtPt.java @@ -0,0 +1,16 @@ +package com.alibaba.cola.test.customer.validator.extensionpoint; + +import com.alibaba.cola.extension.ExtensionPointI; +import com.alibaba.cola.test.customer.AddCustomerCmd; +import com.alibaba.cola.test.customer.entity.CustomerEntity; + +/** + * AddCustomerValidatorExtPt + * + * @author Frank Zhang + * @date 2018-01-07 1:27 AM + */ +public interface AddCustomerValidatorExtPt extends ExtensionPointI { + + public void validate(AddCustomerCmd addCustomerCmd); +} diff --git a/cola-framework-core/src/test/resources/sample.properties b/cola-framework-core/src/test/resources/sample.properties new file mode 100644 index 000000000..9c246053e --- /dev/null +++ b/cola-framework-core/src/test/resources/sample.properties @@ -0,0 +1 @@ +bizCode=BIZ_ONE