xueli.xue 9 jaren geleden
bovenliggende
commit
628d421941

+ 2 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/jobbean/RemoteHttpJobBean.java Bestand weergeven

52
 
52
 
53
 		params.put(HandlerParamEnum.JOB_GROUP.name(), jobInfo.getJobGroup());
53
 		params.put(HandlerParamEnum.JOB_GROUP.name(), jobInfo.getJobGroup());
54
 		params.put(HandlerParamEnum.JOB_NAME.name(), jobInfo.getJobName());
54
 		params.put(HandlerParamEnum.JOB_NAME.name(), jobInfo.getJobName());
55
+		params.put(HandlerParamEnum.EXECUTOR_HANDLER.name(), jobInfo.getExecutorHandler());
55
 		params.put(HandlerParamEnum.EXECUTOR_PARAMS.name(), jobInfo.getExecutorParam());
56
 		params.put(HandlerParamEnum.EXECUTOR_PARAMS.name(), jobInfo.getExecutorParam());
56
 
57
 
57
 		params.put(HandlerParamEnum.GLUE_SWITCH.name(), String.valueOf(jobInfo.getGlueSwitch()));
58
 		params.put(HandlerParamEnum.GLUE_SWITCH.name(), String.valueOf(jobInfo.getGlueSwitch()));
58
 
59
 
59
 		// failover trigger
60
 		// failover trigger
60
 		RemoteCallBack callback = failoverTrigger(jobInfo.getExecutorAddress(), params, jobLog);
61
 		RemoteCallBack callback = failoverTrigger(jobInfo.getExecutorAddress(), params, jobLog);
62
+		jobLog.setExecutorHandler(jobInfo.getExecutorHandler());
61
 		jobLog.setExecutorParam(jobInfo.getExecutorParam());
63
 		jobLog.setExecutorParam(jobInfo.getExecutorParam());
62
 		logger.info(">>>>>>>>>>> xxl-job failoverTrigger response, jobId:{}, callback:{}", jobLog.getId(), callback);
64
 		logger.info(">>>>>>>>>>> xxl-job failoverTrigger response, jobId:{}, callback:{}", jobLog.getId(), callback);
63
 		
65
 		

+ 7 - 0
xxl-job-admin/src/main/java/com/xxl/job/admin/core/model/XxlJobLog.java Bestand weergeven

15
 	private String jobName;
15
 	private String jobName;
16
 	
16
 	
17
 	private String executorAddress;	// 执行器地址,有多个则逗号分隔
17
 	private String executorAddress;	// 执行器地址,有多个则逗号分隔
18
+	private String executorHandler;	// 执行器Handler
18
 	private String executorParam;	// 执行器,任务参数
19
 	private String executorParam;	// 执行器,任务参数
19
 	
20
 	
20
 	// trigger info
21
 	// trigger info
51
 	public void setExecutorAddress(String executorAddress) {
52
 	public void setExecutorAddress(String executorAddress) {
52
 		this.executorAddress = executorAddress;
53
 		this.executorAddress = executorAddress;
53
 	}
54
 	}
55
+	public String getExecutorHandler() {
56
+		return executorHandler;
57
+	}
58
+	public void setExecutorHandler(String executorHandler) {
59
+		this.executorHandler = executorHandler;
60
+	}
54
 	public String getExecutorParam() {
61
 	public String getExecutorParam() {
55
 		return executorParam;
62
 		return executorParam;
56
 	}
63
 	}

+ 10 - 2
xxl-job-admin/src/main/java/com/xxl/job/admin/core/thread/JobMonitorHelper.java Bestand weergeven

10
 import org.slf4j.LoggerFactory;
10
 import org.slf4j.LoggerFactory;
11
 
11
 
12
 import java.text.MessageFormat;
12
 import java.text.MessageFormat;
13
+import java.util.Arrays;
14
+import java.util.HashSet;
15
+import java.util.Set;
13
 import java.util.concurrent.*;
16
 import java.util.concurrent.*;
14
 
17
 
15
 /**
18
 /**
51
 								if (RemoteCallBack.FAIL.equals(log.getTriggerStatus()) || RemoteCallBack.FAIL.equals(log.getHandleStatus())) {
54
 								if (RemoteCallBack.FAIL.equals(log.getTriggerStatus()) || RemoteCallBack.FAIL.equals(log.getHandleStatus())) {
52
 									XxlJobInfo info = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
55
 									XxlJobInfo info = DynamicSchedulerUtil.xxlJobInfoDao.load(log.getJobGroup(), log.getJobName());
53
 									if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
56
 									if (info!=null && info.getAlarmEmail()!=null && info.getAlarmEmail().trim().length()>0) {
54
-										MailUtil.sendMail(info.getAlarmEmail(), "《调度监控报警-调度平台平台XXL-JOB》",
55
-												MessageFormat.format("任务调度失败, 任务组:{0}, 任务描述:{1}.", info.getJobGroup(), info.getJobDesc()), false, null);
57
+
58
+										Set<String> emailSet = new HashSet<String>(Arrays.asList(info.getAlarmEmail().split(",")));
59
+										for (String email: emailSet) {
60
+											String title = "《调度监控报警-调度平台平台XXL-JOB》";
61
+											String content = MessageFormat.format("任务调度失败, 任务组:{0}, 任务描述:{1}.", info.getJobGroup(), info.getJobDesc());
62
+											MailUtil.sendMail(email, title, content, false, null);
63
+										}
56
 									}
64
 									}
57
 								}
65
 								}
58
 							}
66
 							}

+ 5 - 0
xxl-job-admin/src/main/resources/mybatis-mapper/XxlJobLogMapper.xml Bestand weergeven

10
 	    <result column="job_name" property="jobName" />
10
 	    <result column="job_name" property="jobName" />
11
 	    
11
 	    
12
 	    <result column="executor_address" property="executorAddress" />
12
 	    <result column="executor_address" property="executorAddress" />
13
+		<result column="executor_handler" property="executorHandler" />
13
 	    <result column="executor_param" property="executorParam" />
14
 	    <result column="executor_param" property="executorParam" />
14
 	    
15
 	    
15
 	    <result column="trigger_time" property="triggerTime" />
16
 	    <result column="trigger_time" property="triggerTime" />
27
 		t.job_group,
28
 		t.job_group,
28
 		t.job_name,
29
 		t.job_name,
29
 		t.executor_address,
30
 		t.executor_address,
31
+		t.executor_handler,
30
 		t.executor_param,
32
 		t.executor_param,
31
 		t.trigger_time,
33
 		t.trigger_time,
32
 		t.trigger_status,
34
 		t.trigger_status,
94
 			`job_group`,
96
 			`job_group`,
95
 			`job_name`,
97
 			`job_name`,
96
 			`executor_address`,
98
 			`executor_address`,
99
+			`executor_handler`,
97
 			`executor_param`
100
 			`executor_param`
98
 		) VALUES (
101
 		) VALUES (
99
 			#{jobGroup}, 
102
 			#{jobGroup}, 
100
 			#{jobName},
103
 			#{jobName},
101
 			#{executorAddress},
104
 			#{executorAddress},
105
+			#{executorHandler},
102
 			#{executorParam}
106
 			#{executorParam}
103
 		);
107
 		);
104
 		<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> 
108
 		<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> 
113
 			`trigger_status`= #{triggerStatus}, 
117
 			`trigger_status`= #{triggerStatus}, 
114
 			`trigger_msg`= #{triggerMsg},
118
 			`trigger_msg`= #{triggerMsg},
115
 			`executor_address`= #{executorAddress},
119
 			`executor_address`= #{executorAddress},
120
+			`executor_handler`=#{executorHandler},
116
 			`executor_param`= #{executorParam}
121
 			`executor_param`= #{executorParam}
117
 		WHERE `id`= #{id}
122
 		WHERE `id`= #{id}
118
 	</update>
123
 	</update>

+ 3 - 3
xxl-job-admin/src/main/webapp/WEB-INF/template/jobinfo/jobinfo.index.ftl Bestand weergeven

40
 	    	<div class="row">
40
 	    	<div class="row">
41
 	    		<div class="col-xs-4">
41
 	    		<div class="col-xs-4">
42
 	              	<div class="input-group">
42
 	              	<div class="input-group">
43
-	                	<span class="input-group-addon">组</span>
43
+	                	<span class="input-group-addon">任务组</span>
44
                 		<select class="form-control" id="jobGroup" >
44
                 		<select class="form-control" id="jobGroup" >
45
                 			<#list JobGroupList as group>
45
                 			<#list JobGroupList as group>
46
                 				<option value="${group}" >${group.desc}</option>
46
                 				<option value="${group}" >${group.desc}</option>
113
          	<div class="modal-body">
113
          	<div class="modal-body">
114
 				<form class="form-horizontal form" role="form" >
114
 				<form class="form-horizontal form" role="form" >
115
 					<div class="form-group">
115
 					<div class="form-group">
116
-						<label for="firstname" class="col-sm-2 control-label">组<font color="red">*</font></label>
116
+						<label for="firstname" class="col-sm-2 control-label">任务组<font color="red">*</font></label>
117
 						<div class="col-sm-4">
117
 						<div class="col-sm-4">
118
 							<select class="form-control" name="jobGroup" >
118
 							<select class="form-control" name="jobGroup" >
119
 		            			<#list JobGroupList as group>
119
 		            			<#list JobGroupList as group>
194
          	<div class="modal-body">
194
          	<div class="modal-body">
195
 				<form class="form-horizontal form" role="form" >
195
 				<form class="form-horizontal form" role="form" >
196
 					<div class="form-group">
196
 					<div class="form-group">
197
-                        <label for="firstname" class="col-sm-2 control-label">组<font color="red">*</font></label>
197
+                        <label for="firstname" class="col-sm-2 control-label">任务组<font color="red">*</font></label>
198
                         <div class="col-sm-4">
198
                         <div class="col-sm-4">
199
 							<input type="text" class="form-control jobGroupTitle" maxlength="50" readonly >
199
 							<input type="text" class="form-control jobGroupTitle" maxlength="50" readonly >
200
 						</div>
200
 						</div>

+ 3 - 2
xxl-job-admin/src/main/webapp/WEB-INF/template/joblog/joblog.index.ftl Bestand weergeven

34
 	    	<div class="row">
34
 	    	<div class="row">
35
 	    		<div class="col-xs-3">
35
 	    		<div class="col-xs-3">
36
  					<div class="input-group">
36
  					<div class="input-group">
37
-	                	<span class="input-group-addon">组</span>
37
+	                	<span class="input-group-addon">任务组</span>
38
                 		<select class="form-control" id="jobGroup"  paramVal="${jobGroup}" >
38
                 		<select class="form-control" id="jobGroup"  paramVal="${jobGroup}" >
39
                             <option value="" selected>请选择</option>
39
                             <option value="" selected>请选择</option>
40
                 			<#list JobGroupList as group>
40
                 			<#list JobGroupList as group>
45
 	            </div>
45
 	            </div>
46
 	            <div class="col-xs-3">
46
 	            <div class="col-xs-3">
47
 	              	<div class="input-group">
47
 	              	<div class="input-group">
48
-	                	<span class="input-group-addon">名称</span>
48
+	                	<span class="input-group-addon">描述</span>
49
                         <select class="form-control" id="jobName" paramVal="${jobName}" >
49
                         <select class="form-control" id="jobName" paramVal="${jobName}" >
50
                             <option value="" >请选择</option>
50
                             <option value="" >请选择</option>
51
 						</select>
51
 						</select>
79
 					                	<th name="jobGroup" >任务组</th>
79
 					                	<th name="jobGroup" >任务组</th>
80
 					                  	<th name="jobName" >任务名</th>
80
 					                  	<th name="jobName" >任务名</th>
81
 					                  	<th name="executorAddress" >执行器地址</th>
81
 					                  	<th name="executorAddress" >执行器地址</th>
82
+                                        <th name="executorHandler" >JobHandler</th>
82
 					                  	<th name="executorParam" >任务参数</th>
83
 					                  	<th name="executorParam" >任务参数</th>
83
 					                  	<th name="triggerTime" >调度时间</th>
84
 					                  	<th name="triggerTime" >调度时间</th>
84
 					                  	<th name="triggerStatus" >调度结果</th>
85
 					                  	<th name="triggerStatus" >调度结果</th>

+ 2 - 1
xxl-job-admin/src/main/webapp/static/js/joblog.index.1.js Bestand weergeven

1
 $(function() {
1
 $(function() {
2
 
2
 
3
-	// 组列表选中, 任务列表初始化和选中
3
+	// 任务组列表选中, 任务列表初始化和选中
4
     var ifParam = true;
4
     var ifParam = true;
5
 	$("#jobGroup").on("change", function () {
5
 	$("#jobGroup").on("change", function () {
6
 		var jobGroup = $(this).children('option:selected').val();
6
 		var jobGroup = $(this).children('option:selected').val();
97
             		},
97
             		},
98
 	                { "data": 'jobName', "visible" : false},
98
 	                { "data": 'jobName', "visible" : false},
99
 	                { "data": 'executorAddress', "visible" : true},
99
 	                { "data": 'executorAddress', "visible" : true},
100
+					{ "data": 'executorHandler', "visible" : true},
100
 	                { "data": 'executorParam', "visible" : true},
101
 	                { "data": 'executorParam', "visible" : true},
101
 	                { 
102
 	                { 
102
 	                	"data": 'triggerTime', 
103
 	                	"data": 'triggerTime', 

+ 7 - 13
xxl-job-core/src/main/java/com/xxl/job/core/executor/jetty/XxlJobExecutor.java Bestand weergeven

1
 package com.xxl.job.core.executor.jetty;
1
 package com.xxl.job.core.executor.jetty;
2
 
2
 
3
-import java.util.*;
4
-
3
+import com.xxl.job.core.handler.HandlerRepository;
4
+import com.xxl.job.core.handler.IJobHandler;
5
+import com.xxl.job.core.handler.annotation.JobHander;
5
 import org.eclipse.jetty.server.Connector;
6
 import org.eclipse.jetty.server.Connector;
6
 import org.eclipse.jetty.server.Handler;
7
 import org.eclipse.jetty.server.Handler;
7
 import org.eclipse.jetty.server.Server;
8
 import org.eclipse.jetty.server.Server;
14
 import org.springframework.context.ApplicationContext;
15
 import org.springframework.context.ApplicationContext;
15
 import org.springframework.context.ApplicationContextAware;
16
 import org.springframework.context.ApplicationContextAware;
16
 
17
 
17
-import com.xxl.job.core.handler.HandlerRepository;
18
-import com.xxl.job.core.handler.IJobHandler;
19
-import com.xxl.job.core.handler.annotation.JobHander;
18
+import java.util.Map;
20
 
19
 
21
 /**
20
 /**
22
  * Created by xuxueli on 2016/3/2 21:14.
21
  * Created by xuxueli on 2016/3/2 21:14.
89
         if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
88
         if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
90
             for (Object serviceBean : serviceBeanMap.values()) {
89
             for (Object serviceBean : serviceBeanMap.values()) {
91
                 if (serviceBean instanceof IJobHandler){
90
                 if (serviceBean instanceof IJobHandler){
92
-                    String jobKeys = serviceBean.getClass().getAnnotation(JobHander.class).value();
93
-                    if (jobKeys!=null && jobKeys.trim().length()>0) {
94
-                        Set<String> jobKeySet = new HashSet<String>(Arrays.asList(jobKeys.split(",")));
95
-                        for (String jobKey : jobKeySet) {
96
-                            IJobHandler handler = (IJobHandler) serviceBean;
97
-                            HandlerRepository.regist(jobKey, handler);
98
-                        }
99
-                    }
91
+                    String name = serviceBean.getClass().getAnnotation(JobHander.class).value();
92
+                    IJobHandler handler = (IJobHandler) serviceBean;
93
+                    HandlerRepository.registJobHandler(name, handler);
100
                 }
94
                 }
101
             }
95
             }
102
         }
96
         }

+ 48 - 18
xxl-job-core/src/main/java/com/xxl/job/core/handler/HandlerRepository.java Bestand weergeven

41
 		/**
41
 		/**
42
 		 * params of jobhandler
42
 		 * params of jobhandler
43
 		 */
43
 		 */
44
+		EXECUTOR_HANDLER,
45
+		/**
46
+		 * params of jobhandler
47
+		 */
44
 		EXECUTOR_PARAMS,
48
 		EXECUTOR_PARAMS,
45
 		/**
49
 		/**
46
 		 * switch of glue job: 0-no,1-yes
50
 		 * switch of glue job: 0-no,1-yes
60
 		LOG_DATE
64
 		LOG_DATE
61
 	}
65
 	}
62
 	public enum ActionEnum{RUN, KILL, LOG, BEAT}
66
 	public enum ActionEnum{RUN, KILL, LOG, BEAT}
63
-	
67
+
68
+	// jobhandler repository
69
+	private static ConcurrentHashMap<String, IJobHandler> handlerRepository = new ConcurrentHashMap<String, IJobHandler>();
70
+	public static void registJobHandler(String name, IJobHandler jobHandler){
71
+		handlerRepository.put(name, jobHandler);
72
+		logger.info("xxl-job register jobhandler success, name:{}, jobHandler:{}", name, jobHandler);
73
+	}
74
+
75
+	// thread repository of jobhandler
64
 	public static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
76
 	public static ConcurrentHashMap<String, HandlerThread> handlerTreadMap = new ConcurrentHashMap<String, HandlerThread>();
65
-	
66
-	// regist handler
67
-	public static void regist(String handleName, IJobHandler handler){
77
+	public static HandlerThread registJobHandlerThread(String jobkey, IJobHandler handler){
68
 		HandlerThread handlerThread = new HandlerThread(handler);
78
 		HandlerThread handlerThread = new HandlerThread(handler);
69
 		handlerThread.start();
79
 		handlerThread.start();
70
-		handlerTreadMap.put(handleName, handlerThread);	// putIfAbsent
71
-		logger.info(">>>>>>>>>>> xxl-job regist handler success, handleName:{}, handler:{}", new Object[]{handleName, handler});
80
+		logger.info(">>>>>>>>>>> xxl-job regist handler success, jobkey:{}, handler:{}", new Object[]{jobkey, handler});
81
+		return handlerTreadMap.put(jobkey, handlerThread);	// putIfAbsent
72
 	}
82
 	}
73
-	
83
+
74
 	// handler push to queue
84
 	// handler push to queue
75
 	public static String service(Map<String, String> _param) {
85
 	public static String service(Map<String, String> _param) {
76
 		logger.debug(">>>>>>>>>>> xxl-job service start, _param:{}", new Object[]{_param});
86
 		logger.debug(">>>>>>>>>>> xxl-job service start, _param:{}", new Object[]{_param});
77
-		
87
+
78
 		// callback
88
 		// callback
79
 		RemoteCallBack callback = new RemoteCallBack();
89
 		RemoteCallBack callback = new RemoteCallBack();
80
 		callback.setStatus(RemoteCallBack.FAIL);
90
 		callback.setStatus(RemoteCallBack.FAIL);
91
 			callback.setMsg("Timestamp check failed.");
101
 			callback.setMsg("Timestamp check failed.");
92
 			return JacksonUtil.writeValueAsString(callback);
102
 			return JacksonUtil.writeValueAsString(callback);
93
 		}
103
 		}
94
-					
104
+
95
 		// parse namespace
105
 		// parse namespace
96
 		if (namespace.equals(ActionEnum.RUN.name())) {
106
 		if (namespace.equals(ActionEnum.RUN.name())) {
97
 
107
 
110
 				return JacksonUtil.writeValueAsString(callback);
120
 				return JacksonUtil.writeValueAsString(callback);
111
 			}
121
 			}
112
 
122
 
123
+			// load old thread
113
 			String jobKey = job_group.concat("_").concat(job_name);
124
 			String jobKey = job_group.concat("_").concat(job_name);
114
 			HandlerThread handlerThread = handlerTreadMap.get(jobKey);
125
 			HandlerThread handlerThread = handlerTreadMap.get(jobKey);
126
+
115
 			if ("0".equals(handler_glue_switch)) {
127
 			if ("0".equals(handler_glue_switch)) {
116
 				// bean model
128
 				// bean model
117
-				if (handlerThread == null) {
118
-					callback.setMsg("handler for jobKey=[" + jobKey + "] not found.");
129
+
130
+				// handler name
131
+				String executor_handler = _param.get(HandlerParamEnum.EXECUTOR_HANDLER.name());
132
+				if (executor_handler==null || executor_handler.trim().length()==0){
133
+					callback.setMsg("EXECUTOR_HANDLER is null.");
119
 					return JacksonUtil.writeValueAsString(callback);
134
 					return JacksonUtil.writeValueAsString(callback);
120
 				}
135
 				}
136
+
137
+				// handler instance
138
+				IJobHandler jobHandler = handlerRepository.get(executor_handler);
139
+
140
+				if (handlerThread == null) {
141
+					// jobhandler match
142
+					if (jobHandler==null) {
143
+						callback.setMsg("handler for jobKey=[" + jobKey + "] not found.");
144
+						return JacksonUtil.writeValueAsString(callback);
145
+					}
146
+					handlerThread = HandlerRepository.registJobHandlerThread(jobKey, jobHandler);
147
+				} else {
148
+					if (handlerThread.getHandler() != jobHandler) {
149
+						handlerThread = HandlerRepository.registJobHandlerThread(jobKey, jobHandler);
150
+					}
151
+				}
121
 			} else {
152
 			} else {
122
 				// glue
153
 				// glue
123
-				if (handlerThread==null) {
124
-					HandlerRepository.regist(jobKey, new GlueJobHandler(job_group, job_name));
154
+				if (handlerThread == null) {
155
+					handlerThread = HandlerRepository.registJobHandlerThread(jobKey, new GlueJobHandler(job_group, job_name));
125
 				}
156
 				}
126
-				handlerThread = handlerTreadMap.get(jobKey);
127
 			}
157
 			}
128
 
158
 
129
 			// push data to queue
159
 			// push data to queue
145
 				IJobHandler handler = handlerThread.getHandler();
175
 				IJobHandler handler = handlerThread.getHandler();
146
 				handlerThread.toStop();
176
 				handlerThread.toStop();
147
 				handlerThread.interrupt();
177
 				handlerThread.interrupt();
148
-				regist(jobKey, handler);
178
+				HandlerRepository.registJobHandlerThread(jobKey, handler);
149
 				callback.setStatus(RemoteCallBack.SUCCESS);
179
 				callback.setStatus(RemoteCallBack.SUCCESS);
150
 			} else {
180
 			} else {
151
 				callback.setMsg("handler for jobKey=[" + jobKey + "] not found.");
181
 				callback.setMsg("handler for jobKey=[" + jobKey + "] not found.");
179
 			callback.setMsg("param[Action] is not valid.");
209
 			callback.setMsg("param[Action] is not valid.");
180
 			return JacksonUtil.writeValueAsString(callback);
210
 			return JacksonUtil.writeValueAsString(callback);
181
 		}
211
 		}
182
-		
212
+
183
 		logger.debug(">>>>>>>>>>> xxl-job service end, triggerData:{}");
213
 		logger.debug(">>>>>>>>>>> xxl-job service end, triggerData:{}");
184
-		return JacksonUtil.writeValueAsString(callback); 
214
+		return JacksonUtil.writeValueAsString(callback);
185
 	}
215
 	}
186
-	
216
+
187
 	// ----------------------- for callback log -----------------------
217
 	// ----------------------- for callback log -----------------------
188
 	private static LinkedBlockingQueue<HashMap<String, String>> callBackQueue = new LinkedBlockingQueue<HashMap<String, String>>();
218
 	private static LinkedBlockingQueue<HashMap<String, String>> callBackQueue = new LinkedBlockingQueue<HashMap<String, String>>();
189
 	static {
219
 	static {

+ 1 - 1
xxl-job-executor-example/src/main/java/com/xxl/job/executor/service/jobhandler/DemoJobHandler.java Bestand weergeven

20
  * 
20
  * 
21
  * @author xuxueli 2015-12-19 19:43:36
21
  * @author xuxueli 2015-12-19 19:43:36
22
  */
22
  */
23
-@JobHander(value="waimai_201607202316260736,waimai_201607202316260736")
23
+@JobHander(value="demoJobHandler")
24
 @Service
24
 @Service
25
 public class DemoJobHandler extends IJobHandler {
25
 public class DemoJobHandler extends IJobHandler {
26
 	private static transient Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);
26
 	private static transient Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);