<|start_filename|>gateway/src/main/java/me/batizhao/cloud/ApiGatewayZuulApplication.java<|end_filename|>
package me.batizhao.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 * @author batizhao
 * @since 2017/2/24
 */
@SpringBootApplication
@EnableZuulProxy
public class ApiGatewayZuulApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayZuulApplication.class, args);
    }

}


<|start_filename|>engine/src/main/java/me/batizhao/cloud/service/UserService.java<|end_filename|>
package me.batizhao.cloud.service;

import org.springframework.stereotype.Service;

/**
 * @author batizhao
 * @since 2017/2/21
 */
@Service
public class UserService {

    public void storeResume() {
        System.out.println("Storing resume ...");
    }

}


<|start_filename|>engine/src/main/java/me/batizhao/cloud/repository/UserRepository.java<|end_filename|>
package me.batizhao.cloud.repository;

import me.batizhao.cloud.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @author batizhao
 * @since 2017/2/21
 */
public interface UserRepository extends JpaRepository<User, Long> {
}


<|start_filename|>engine/src/main/java/me/batizhao/cloud/FlowEngineServerApplication.java<|end_filename|>
package me.batizhao.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class FlowEngineServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(FlowEngineServerApplication.class, args);
	}

//	@Bean
//	InitializingBean usersAndGroupsInitializer(final IdentityService identityService) {
//
//		return new InitializingBean() {
//			public void afterPropertiesSet() throws Exception {
//
//				Group group = identityService.newGroup("user");
//				group.setName("users");
//				group.setType("security-role");
//				identityService.saveGroup(group);
//
//				User admin = identityService.newUser("admin");
//				admin.setPassword("<PASSWORD>");
//				identityService.saveUser(admin);
//
//			}
//		};
//	}
}


<|start_filename|>engine/src/main/java/me/batizhao/cloud/controller/ActivitiController.java<|end_filename|>
package me.batizhao.cloud.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import me.batizhao.cloud.service.WorkflowProcessDefinitionService;
import me.batizhao.cloud.service.WorkflowTraceService;
import me.batizhao.cloud.util.WorkflowUtils;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.*;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.repository.Deployment;
//import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

/**
 * 流程管理控制器
 *
 * @author HenryYan
 */
@Controller
@RequestMapping(value = "activiti")
public class ActivitiController {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected WorkflowProcessDefinitionService workflowProcessDefinitionService;

    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected RuntimeService runtimeService;

    @Autowired
    protected TaskService taskService;

    @Autowired
    protected WorkflowTraceService traceService;

    @Autowired
    ManagementService managementService;

    @Autowired
    ProcessEngineFactoryBean processEngine;

    @Autowired
    ProcessEngineConfiguration processEngineConfiguration;

    /**
     * 流程定义列表
     *
     * @return
     */
    @GetMapping(value = "/processes")
    public String processList(Model model) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc();
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.list();
        model.addAttribute("processDefinitionList", processDefinitionList);
        return "workflow/processes";
    }

    /**
     * 部署全部流程
     *
     * @return
     * @throws Exception
     */
//    @RequestMapping(value = "/redeploy/all")
//    public String redeployAll(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws Exception {
//        workflowProcessDefinitionService.deployAllFromClasspath(exportDir);
//        return "redirect:/workflow/process-list";
//    }

    /**
     * 读取资源，通过部署ID
     *
     * @param processDefinitionId 流程定义
     * @param resourceType        资源类型(xml|image)
     * @throws Exception
     */
    @RequestMapping(value = "/resource/read")
    public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId,
                                 @RequestParam("resourceType") String resourceType,
                                 HttpServletResponse response) throws Exception {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        String resourceName = "";
        if (resourceType.equals("image")) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (resourceType.equals("xml")) {
            resourceName = processDefinition.getResourceName();
        }
        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

    /**
     * 读取资源，通过流程ID
     *
     * @param resourceType      资源类型(xml|image)
     * @param processInstanceId 流程实例ID
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/resource/process-instance")
    public void loadByProcessInstance(@RequestParam("type") String resourceType, @RequestParam("pid") String processInstanceId, HttpServletResponse response)
            throws Exception {
        InputStream resourceAsStream = null;
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId())
                .singleResult();

        String resourceName = "";
        if (resourceType.equals("image")) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (resourceType.equals("xml")) {
            resourceName = processDefinition.getResourceName();
        }
        resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

    /**
     * 删除部署的流程，级联删除流程实例
     *
     * @param deploymentId 流程部署ID
     */
    @RequestMapping(value = "/process/delete")
    public String delete(@RequestParam("deploymentId") String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
        return "redirect:/workflow/process-list";
    }

    /**
     * 输出跟踪流程信息
     *
     * @param processInstanceId
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/process/trace")
    @ResponseBody
    public List<Map<String, Object>> traceProcess(@RequestParam("pid") String processInstanceId) throws Exception {
        List<Map<String, Object>> activityInfos = traceService.traceProcess(processInstanceId);
        return activityInfos;
    }

    /**
     * 读取带跟踪的图片
     */
    @RequestMapping(value = "/process/trace/auto/{executionId}")
    public void readResource(@PathVariable("executionId") String executionId, HttpServletResponse response)
            throws Exception {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        List<String> activeActivityIds = runtimeService.getActiveActivityIds(executionId);
        // 不使用spring请使用下面的两行代码
//    ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();
//    Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());

        // 使用spring注入引擎请使用下面的这行代码
        processEngineConfiguration = processEngine.getProcessEngineConfiguration();
        Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

        ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
        InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds);

        // 输出资源内容到相应对象
        byte[] b = new byte[1024];
        int len;
        while ((len = imageStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

    @RequestMapping(value = "/deploy")
    public String deploy(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir, @RequestParam(value = "file", required = false) MultipartFile file) {

        String fileName = file.getOriginalFilename();

        try {
            InputStream fileInputStream = file.getInputStream();
            Deployment deployment = null;

            String extension = FilenameUtils.getExtension(fileName);
            if (extension.equals("zip") || extension.equals("bar")) {
                ZipInputStream zip = new ZipInputStream(fileInputStream);
                deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy();
            } else {
                deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
            }

            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();

            for (ProcessDefinition processDefinition : list) {
                WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir);
            }

        } catch (Exception e) {
            logger.error("error on deploy process, because of file input stream", e);
        }

        return "redirect:/workflow/process-list";
    }

//    @RequestMapping(value = "/process/convert-to-model/{processDefinitionId}")
//    public String convertToModel(@PathVariable("processDefinitionId") String processDefinitionId)
//            throws UnsupportedEncodingException, XMLStreamException {
//        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
//                .processDefinitionId(processDefinitionId).singleResult();
//        InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
//                processDefinition.getResourceName());
//        XMLInputFactory xif = XMLInputFactory.newInstance();
//        InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
//        XMLStreamReader xtr = xif.createXMLStreamReader(in);
//        BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
//
//        BpmnJsonConverter converter = new BpmnJsonConverter();
//        com.fasterxml.jackson.databind.node.ObjectNode modelNode = converter.convertToJson(bpmnModel);
//        Model modelData = repositoryService.newModel();
//        modelData.setKey(processDefinition.getKey());
//        modelData.setName(processDefinition.getResourceName());
//        modelData.setCategory(processDefinition.getDeploymentId());
//
//        ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
//        modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
//        modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
//        modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
//        modelData.setMetaInfo(modelObjectNode.toString());
//
//        repositoryService.saveModel(modelData);
//
//        repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
//
//        return "redirect:/workflow/model/list";
//    }

    /**
     * 待办任务--Portlet
     */
//    @RequestMapping(value = "/task/todo/list")
//    @ResponseBody
//    public List<Map<String, Object>> todoList(HttpSession session) throws Exception {
//        User user = UserUtil.getUserFromSession(session);
//        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm");
//
//        // 已经签收的任务
//        List<Task> todoList = taskService.createTaskQuery().taskAssignee(user.getId()).active().list();
//        for (Task task : todoList) {
//            String processDefinitionId = task.getProcessDefinitionId();
//            ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);
//
//            Map<String, Object> singleTask = packageTaskInfo(sdf, task, processDefinition);
//            singleTask.put("status", "todo");
//            result.add(singleTask);
//        }
//
//        // 等待签收的任务
//        List<Task> toClaimList = taskService.createTaskQuery().taskCandidateUser(user.getId()).active().list();
//        for (Task task : toClaimList) {
//            String processDefinitionId = task.getProcessDefinitionId();
//            ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId);
//
//            Map<String, Object> singleTask = packageTaskInfo(sdf, task, processDefinition);
//            singleTask.put("status", "claim");
//            result.add(singleTask);
//        }
//
//        return result;
//    }

    private Map<String, Object> packageTaskInfo(SimpleDateFormat sdf, Task task, ProcessDefinition processDefinition) {
        Map<String, Object> singleTask = new HashMap<String, Object>();
        singleTask.put("id", task.getId());
        singleTask.put("name", task.getName());
        singleTask.put("createTime", sdf.format(task.getCreateTime()));
        singleTask.put("pdname", processDefinition.getName());
        singleTask.put("pdversion", processDefinition.getVersion());
        singleTask.put("pid", task.getProcessInstanceId());
        return singleTask;
    }

//    private ProcessDefinition getProcessDefinition(String processDefinitionId) {
//        ProcessDefinition processDefinition = PROCESS_DEFINITION_CACHE.get(processDefinitionId);
//        if (processDefinition == null) {
//            processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
//            PROCESS_DEFINITION_CACHE.put(processDefinitionId, processDefinition);
//        }
//        return processDefinition;
//    }

    /**
     * 挂起、激活流程实例
     */
    @RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}")
    public String updateState(@PathVariable("state") String state, @PathVariable("processDefinitionId") String processDefinitionId,
                              RedirectAttributes redirectAttributes) {
        if (state.equals("active")) {
            redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processDefinitionId + "]的流程定义。");
            repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
        } else if (state.equals("suspend")) {
            repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
            redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processDefinitionId + "]的流程定义。");
        }
        return "redirect:/workflow/process-list";
    }

    /**
     * 导出图片文件到硬盘
     *
     * @return
     */
    @RequestMapping(value = "export/diagrams")
    @ResponseBody
    public List<String> exportDiagrams(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws IOException {
        List<String> files = new ArrayList<String>();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();

        for (ProcessDefinition processDefinition : list) {
            files.add(WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir));
        }

        return files;
    }

//    @RequestMapping(value = "activity/jump")
//    @ResponseBody
//    public boolean jump(@RequestParam("executionId") String executionId,
//                        @RequestParam("activityId") String activityId) {
//        Command<Object> cmd = new JumpActivityCmd(executionId, activityId);
//        managementService.executeCommand(cmd);
//        return true;
//    }

    @RequestMapping(value = "bpmn/model/{processDefinitionId}")
    @ResponseBody
    public BpmnModel queryBpmnModel(@PathVariable("processDefinitionId") String processDefinitionId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        return bpmnModel;
    }

}

<|start_filename|>oa/src/main/java/me/batizhao/cloud/service/OaClientService.java<|end_filename|>
package me.batizhao.cloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import me.batizhao.cloud.domain.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * @author batizhao
 * @since 2017/2/24
 */
@Service
public class OaClientService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OaClientService.class);

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "fallback")
    public User startProcess(String name, String email, String phoneNumber) {
        User user = new User(name, email, phoneNumber);
        return this.restTemplate.postForObject("http://flow-engine-server/start-process", user, User.class);
    }

    /**
     * hystrix fallback方法
     * @return 默认的用户
     */
    public User fallback(String name, String email, String phoneNumber) {
        OaClientService.LOGGER.info("异常发生，进入fallback方法，接收的参数：name = {}", name);
        User user = new User();
        user.setId(-1L);
        user.setName("john");
        user.setEmail("<EMAIL>");
        user.setPhoneNumber("13917891868");
        return user;
    }
}


<|start_filename|>engine/src/main/java/me/batizhao/cloud/controller/UserController.java<|end_filename|>
package me.batizhao.cloud.controller;

import me.batizhao.cloud.domain.User;
import me.batizhao.cloud.repository.UserRepository;
import org.activiti.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.client.ServiceInstance;
//import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author batizhao
 * @since 2017/2/21
 */
@RestController
public class UserController {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private UserRepository userRepository;

//    @Autowired
//    private DiscoveryClient discoveryClient;

    @PostMapping(value="/start-process", produces= MediaType.APPLICATION_JSON_VALUE)
    public User startHireProcess(@RequestBody User data) {

        User user = new User(data.getName(), data.getEmail(), data.getPhoneNumber());
        userRepository.save(user);

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("user", user);
        runtimeService.startProcessInstanceByKey("hireProcessWithJpa", variables);

        return user;
    }

    /**
     * 本地服务实例的信息
     * @return
     */
//    @GetMapping("/instance-info")
//    public ServiceInstance showInfo() {
//        ServiceInstance localServiceInstance = this.discoveryClient.getLocalServiceInstance();
//        return localServiceInstance;
//    }
}


<|start_filename|>oa/src/main/java/me/batizhao/cloud/controller/OaClientController.java<|end_filename|>
package me.batizhao.cloud.controller;

import me.batizhao.cloud.domain.User;
import me.batizhao.cloud.service.OaClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author batizhao
 * @since 2017/2/24
 */
@RestController
@RefreshScope
public class OaClientController {

    @Value("${profile}")
    private String profile;

    @Autowired
    private OaClientService oaClientService;

    @GetMapping("/start")
    public User start() {
        return oaClientService.startProcess("batizhao", "<EMAIL>", "18917778888");
    }

    @GetMapping("/hello")
    public String hello() {
        return this.profile;
    }

}
