Bladeren bron

:feat:自定义注解,拦截请求,记录访问记录发送到kafka

zhangxianyu 1 jaar geleden
bovenliggende
commit
2f9402f22f
16 gewijzigde bestanden met toevoegingen van 589 en 3 verwijderingen
  1. 8 0
      game-data/game-data-serve/pom.xml
  2. 18 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/annotation/Log.java
  3. 74 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/aspectj/LogAspect.java
  4. 43 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/config/KafkaConfig.java
  5. 36 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/config/ThreadPoolConfig.java
  6. 3 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/AdsPromotionDayController.java
  7. 2 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/RoleManageController.java
  8. 56 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/mangae/AsyncManager.java
  9. 35 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/mangae/factory/AsyncFactory.java
  10. 29 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/WebLogDTO.java
  11. 0 2
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/properties/SmsProperties.java
  12. 7 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IWebVisitLogService.java
  13. 49 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/IWebVisitLogServiceImpl.java
  14. 1 1
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/task/OrderCostMonitorAlarmTask.java
  15. 134 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/utils/SpringUtils.java
  16. 94 0
      game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/utils/Threads.java

+ 8 - 0
game-data/game-data-serve/pom.xml

@@ -139,6 +139,14 @@
             <groupId>com.zanxiang.module</groupId>
             <artifactId>zx-sms</artifactId>
         </dependency>
+
+        <!-- kafka -->
+        <dependency>
+            <groupId>org.apache.kafka</groupId>
+            <artifactId>kafka-clients</artifactId>
+            <version>2.2.1</version>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 18 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/annotation/Log.java

@@ -0,0 +1,18 @@
+package com.zanxiang.game.data.serve.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 自定义访问界面日志记录注解
+ */
+@Target({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log
+{
+    /**
+     * 标题
+     */
+    String title() default "";
+
+}

+ 74 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/aspectj/LogAspect.java

@@ -0,0 +1,74 @@
+package com.zanxiang.game.data.serve.aspectj;
+
+
+import com.zanxiang.erp.security.util.SecurityUtil;
+import com.zanxiang.game.data.serve.annotation.Log;
+import com.zanxiang.game.data.serve.mangae.AsyncManager;
+import com.zanxiang.game.data.serve.mangae.factory.AsyncFactory;
+import com.zanxiang.game.data.serve.pojo.dto.WebLogDTO;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class LogAspect {
+    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
+
+    /**
+     * 处理完请求后执行
+     *
+     * @param joinPoint 切点
+     */
+    @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
+    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {
+        handleLog(joinPoint, controllerLog, null, jsonResult);
+    }
+
+    /**
+     * 拦截异常操作
+     *
+     * @param joinPoint 切点
+     * @param e         异常
+     */
+    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
+    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
+        handleLog(joinPoint, controllerLog, e, null);
+    }
+
+    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {
+        try {
+            System.out.println("写入日志");
+
+            //获取当前用户id
+            Long sysUserId = SecurityUtil.getUserId();
+            //标题名称
+            WebLogDTO webLogDTO = new WebLogDTO();
+            webLogDTO.setTitle(controllerLog.title());
+            if(sysUserId!=null){
+                webLogDTO.setUserId(sysUserId.toString());
+            }
+            LocalDateTime now = LocalDateTime.now();
+            String dateTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            webLogDTO.setVisitTime(dateTime);
+            // 发到kafka
+            AsyncManager.me().execute(AsyncFactory.webVisitLog(webLogDTO));
+        } catch (Exception exp) {
+            // 记录日志
+            log.error("==前置通知异常==");
+            log.error("异常信息:{}", exp.getMessage());
+            exp.printStackTrace();
+        }
+    }
+
+}

+ 43 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/config/KafkaConfig.java

@@ -0,0 +1,43 @@
+package com.zanxiang.game.data.serve.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.net.InetAddress;
+import java.util.Properties;
+
+/**
+ * kafka配置
+ */
+@Slf4j
+@Configuration
+public class KafkaConfig {
+
+    @Value("${spring.kafka.game-data.bootstrap-servers}")
+    private String gameSdkKafkaSevers;
+
+    @Bean("gameDataKafkaProducer")
+    public Producer<String, String> gameKafkaProducer() {
+
+        String clientId = "UNKNOWN";
+        try {
+            clientId = InetAddress.getLocalHost().getHostAddress();
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        Properties props = new Properties();
+        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, gameSdkKafkaSevers);
+        props.put(ProducerConfig.CLIENT_ID_CONFIG, clientId);
+        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+        return new KafkaProducer<>(props);
+    }
+
+
+}

+ 36 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/config/ThreadPoolConfig.java

@@ -0,0 +1,36 @@
+package com.zanxiang.game.data.serve.config;
+
+import com.zanxiang.game.data.serve.utils.Threads;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 线程池配置
+ **/
+@Configuration
+public class ThreadPoolConfig {
+    // 核心线程池大小
+    private final int corePoolSize = 10;
+
+
+    /**
+     * 执行周期性或定时任务
+     */
+    @Bean(name = "scheduledExecutorService")
+    protected ScheduledExecutorService scheduledExecutorService() {
+        return new ScheduledThreadPoolExecutor(corePoolSize,
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
+                new ThreadPoolExecutor.CallerRunsPolicy()) {
+            @Override
+            protected void afterExecute(Runnable r, Throwable t) {
+                super.afterExecute(r, t);
+                Threads.printException(r, t);
+            }
+        };
+    }
+}

+ 3 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/AdsPromotionDayController.java

@@ -1,6 +1,7 @@
 package com.zanxiang.game.data.serve.controller;
 
 import com.zanxiang.erp.security.annotation.PreAuthorize;
+import com.zanxiang.game.data.serve.annotation.Log;
 import com.zanxiang.game.data.serve.pojo.dto.PromotionDayDTO;
 import com.zanxiang.game.data.serve.pojo.dto.PromotionDayTotalDTO;
 import com.zanxiang.game.data.serve.pojo.dto.TencentPromotionDayDTO;
@@ -35,6 +36,7 @@ public class AdsPromotionDayController {
     @Autowired
     private IAdsPromotionDayService adsPromotionDayService;
 
+    @Log(title = "头条广告监控")
     @ApiOperation(value = "广告监控数据")
     @PreAuthorize(permissionKey = "promotionData:adsPromotionDay:day")
     @PostMapping("/day")
@@ -63,6 +65,7 @@ public class AdsPromotionDayController {
         return ResultVO.ok(adsPromotionDayService.getPromotionDayTotalData(dto));
     }
 
+    @Log(title = "腾讯广告监控")
     @ApiOperation(value = "腾讯广告监控数据")
     @PreAuthorize(permissionKey = "promotionData:adsAdGroupDay:day")
     @PostMapping("/tencent/day")

+ 2 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/controller/RoleManageController.java

@@ -1,5 +1,6 @@
 package com.zanxiang.game.data.serve.controller;
 
+import com.zanxiang.game.data.serve.annotation.Log;
 import com.zanxiang.game.data.serve.pojo.dto.*;
 import com.zanxiang.game.module.base.pojo.vo.SendMsgResultVO;
 import com.zanxiang.game.module.base.pojo.vo.SendMsgVO;
@@ -30,6 +31,7 @@ public class RoleManageController {
     @Autowired
     private IRoleManageService roleManageService;
 
+    @Log(title = "角色充值排行榜")
     @ApiOperation(value = "角色充值排行榜")
     @PreAuthorize(permissionKey = "roleManage:recharge:role")
     @PostMapping("/rechargeRanking")

+ 56 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/mangae/AsyncManager.java

@@ -0,0 +1,56 @@
+package com.zanxiang.game.data.serve.mangae;
+
+
+
+import com.zanxiang.game.data.serve.utils.SpringUtils;
+import com.zanxiang.game.data.serve.utils.Threads;
+
+import java.util.TimerTask;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 异步任务管理器
+ */
+public class AsyncManager
+{
+    /**
+     * 操作延迟10毫秒
+     */
+    private final int OPERATE_DELAY_TIME = 10;
+
+    /**
+     * 异步操作任务调度线程池
+     */
+    private final ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
+
+    /**
+     * 单例模式
+     */
+    private AsyncManager(){}
+
+    private static final AsyncManager me = new AsyncManager();
+
+    public static AsyncManager me()
+    {
+        return me;
+    }
+
+    /**
+     * 执行任务
+     * 
+     * @param task 任务
+     */
+    public void execute(TimerTask task)
+    {
+        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * 停止任务线程池
+     */
+    public void shutdown()
+    {
+        Threads.shutdownAndAwaitTermination(executor);
+    }
+}

+ 35 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/mangae/factory/AsyncFactory.java

@@ -0,0 +1,35 @@
+package com.zanxiang.game.data.serve.mangae.factory;
+
+
+import com.zanxiang.game.data.serve.pojo.dto.WebLogDTO;
+import com.zanxiang.game.data.serve.service.IWebVisitLogService;
+import com.zanxiang.game.data.serve.utils.SpringUtils;
+
+import java.util.TimerTask;
+
+/**
+ * 异步工厂(产生任务用)
+ * 
+ */
+public class AsyncFactory
+{
+
+    /**
+     * 界面访问记录
+     * 
+     * @param webLogDTO 界面访问记录对象
+     * @return 任务task
+     */
+    public static TimerTask webVisitLog(final WebLogDTO webLogDTO)
+    {
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                // 远程查询操作地点
+                SpringUtils.getBean(IWebVisitLogService.class).insertVisitlog(webLogDTO);
+            }
+        };
+    }
+}

+ 29 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/dto/WebLogDTO.java

@@ -0,0 +1,29 @@
+package com.zanxiang.game.data.serve.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @Description: web界面访问日志对象
+ */
+@Data
+public class WebLogDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 用户id
+     */
+    private String userId;
+
+    /**
+     * 访问时间  YYYY-MM-DD HH:MM:SS
+     */
+    private String visitTime;
+
+}

+ 0 - 2
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/pojo/properties/SmsProperties.java

@@ -4,8 +4,6 @@ import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
 
-import java.util.Set;
-
 @ConfigurationProperties(
         prefix = "ali-sms"
 )

+ 7 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/IWebVisitLogService.java

@@ -0,0 +1,7 @@
+package com.zanxiang.game.data.serve.service;
+
+import com.zanxiang.game.data.serve.pojo.dto.WebLogDTO;
+
+public interface IWebVisitLogService {
+    void insertVisitlog(WebLogDTO webLogDTO);
+}

+ 49 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/service/impl/IWebVisitLogServiceImpl.java

@@ -0,0 +1,49 @@
+package com.zanxiang.game.data.serve.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.zanxiang.game.data.serve.pojo.dto.WebLogDTO;
+import com.zanxiang.game.data.serve.service.IWebVisitLogService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+/**
+ * web访问日志记录
+ */
+@Service
+@Slf4j
+public class IWebVisitLogServiceImpl implements IWebVisitLogService {
+
+
+    @Value("${spring.kafka.game-data.webLogTopic}")
+    private String webLogTopic;
+
+    @Value("${spring.kafka.game-data.bootstrap-servers}")
+    private String gameSdkKafkaSevers;
+
+
+    @Autowired
+    @Qualifier("gameDataKafkaProducer")
+    private Producer<String, String> kafkaProducer;
+
+    /**
+     * 将数据发到kafka
+     * @param webLogDTO
+     */
+    @Override
+    public void insertVisitlog(WebLogDTO webLogDTO) {
+        System.out.println(gameSdkKafkaSevers);
+        String webLogJsonString = JSON.toJSONString(webLogDTO);
+        //将记录发到kafka记录
+        try {
+            kafkaProducer.send(new ProducerRecord<>(this.webLogTopic,webLogJsonString));
+            log.info("发送web访问日志到kafka成功,topic:{},数据为:{}",this.webLogTopic,webLogJsonString);
+        }catch (Exception e){
+            log.error("发送web访问日志到kafka失败,topic:{},数据为:{},异常为:{}",this.webLogTopic,webLogJsonString,e.toString());
+        }
+    }
+}

+ 1 - 1
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/task/OrderCostMonitorAlarmTask.java

@@ -3,7 +3,6 @@ package com.zanxiang.game.data.serve.task;
 import com.zanxiang.game.data.serve.service.IOrderCostMonitorAlarmService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
@@ -30,6 +29,7 @@ public class OrderCostMonitorAlarmTask {
      */
     @Scheduled(cron = "0 0/10 * * * ? ")
     public void run() {
+        //本地不运行
         if(!run){
             return;
         }

+ 134 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/utils/SpringUtils.java

@@ -0,0 +1,134 @@
+package com.zanxiang.game.data.serve.utils;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring工具类 方便在非spring管理环境中获取bean
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware 
+{
+    /** Spring应用上下文环境 */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException 
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException 
+    {
+        SpringUtils.applicationContext = applicationContext;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clz
+     * @return
+     * @throws BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 注册对象的类型
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     * @return
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+
+    /**
+     * 获取当前的环境配置,无配置返回null
+     *
+     * @return 当前的环境配置
+     */
+    public static String[] getActiveProfiles()
+    {
+        return applicationContext.getEnvironment().getActiveProfiles();
+    }
+
+
+}

+ 94 - 0
game-data/game-data-serve/src/main/java/com/zanxiang/game/data/serve/utils/Threads.java

@@ -0,0 +1,94 @@
+package com.zanxiang.game.data.serve.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.*;
+
+/**
+ * 线程相关工具类.
+ */
+public class Threads
+{
+    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
+
+    /**
+     * sleep等待,单位为毫秒
+     */
+    public static void sleep(long milliseconds)
+    {
+        try
+        {
+            Thread.sleep(milliseconds);
+        }
+        catch (InterruptedException e)
+        {
+            return;
+        }
+    }
+
+    /**
+     * 停止线程池
+     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
+     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
+     * 如果仍然超時,則強制退出.
+     * 另对在shutdown时线程本身被调用中断做了处理.
+     */
+    public static void shutdownAndAwaitTermination(ExecutorService pool)
+    {
+        if (pool != null && !pool.isShutdown())
+        {
+            pool.shutdown();
+            try
+            {
+                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                {
+                    pool.shutdownNow();
+                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+                    {
+                        logger.info("Pool did not terminate");
+                    }
+                }
+            }
+            catch (InterruptedException ie)
+            {
+                pool.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+    /**
+     * 打印线程异常信息
+     */
+    public static void printException(Runnable r, Throwable t)
+    {
+        if (t == null && r instanceof Future<?>)
+        {
+            try
+            {
+                Future<?> future = (Future<?>) r;
+                if (future.isDone())
+                {
+                    future.get();
+                }
+            }
+            catch (CancellationException ce)
+            {
+                t = ce;
+            }
+            catch (ExecutionException ee)
+            {
+                t = ee.getCause();
+            }
+            catch (InterruptedException ie)
+            {
+                Thread.currentThread().interrupt();
+            }
+        }
+        if (t != null)
+        {
+            logger.error(t.getMessage(), t);
+        }
+    }
+}