Question

As the title states, I have setup a scheduler in a spring web app and it seems to run in a loop, random times, starting with 8 invocations and then randomly adding. I am using spring version 3.1.3.RELEASE. I am in no way expert on the subject but I have already done the same configuration for scheduling in the past,for about 5-6 other projects. I always add the spring task configuration, like a scheduler and the annotation-driven directive. Then a @Scheduled annotation on the method and that worked like a charm. I have also succeeded scheduling 1 month ago with the same version of Spring, so I believe its not a Spring version issue. I am giving the configuration and bean code below. Please don't hesitate to ask more info :)

Thanks for your time!

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.fileExport</groupId>
  <artifactId>FileExportDaemon</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
        <spring.version>3.1.3.RELEASE</spring.version>
  </properties>

  <dependencies>

        <!-- The SFL4J logging implementation you prefer -->
        <!-- 
         <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-simple</artifactId>
          <version>1.6.1</version>
        </dependency> 
          -->

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version> 
        </dependency>

          <!--
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
             <version>1.7.5</version> 
        </dependency>
          -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>


        <!-- JCR API -->
        <dependency>
          <groupId>javax.jcr</groupId>
          <artifactId>jcr</artifactId>
          <version>2.0</version>
        </dependency>

        <!-- All the Jackrabbit libraries needed for DavEx, plus JcrUtils -->
        <dependency>
            <groupId>org.apache.jackrabbit</groupId>
            <artifactId>jackrabbit-jcr2dav</artifactId>
            <version>2.7.1</version>
        </dependency>



        <dependency>
            <groupId>org.apache.jackrabbit</groupId>
            <artifactId>jackrabbit-api</artifactId>
            <version>2.7.1</version>
        </dependency>


        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.19</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-email</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>


        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2</version>
        </dependency>

        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.4</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>



        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

  </dependencies>

  <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <env>dev</env>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <env>prod</env>
            </properties>
        </profile>
    </profiles>

    <build>
        <finalName>fileExportDaemon</finalName>
        <filters>
            <filter>${env}.properties</filter>
        </filters>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.4.2</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>  


</project>

The application-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:security="http://www.springframework.org/schema/security"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:webflow="http://www.springframework.org/schema/webflow-config"
  xmlns:task="http://www.springframework.org/schema/task"
  xmlns:util="http://www.springframework.org/schema/util"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.1.xsd
          http://www.springframework.org/schema/tx 
          http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
          http://www.springframework.org/schema/jee 
          http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.1.3.xsd
          http://www.springframework.org/schema/mvc 
          http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
          http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
          http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
          http://www.springframework.org/schema/webflow-config
          http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">

    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:configuration.properties</value>
            </list>
        </property>
        <property name="fileEncoding" value="utf-8"/>
    </bean>

    <import resource="fileExportDaemon-service.xml"/>

    <import resource="fileExportDaemon-servlet.xml"/>

    <!-- Tasks Configuration -->
     <task:annotation-driven scheduler="myScheduler" /> 
     <task:scheduler id="myScheduler" pool-size="100" /> 

    <!-- 
    <util:properties id="applicationProps" location="classpath:configuration.properties" />
    <context:property-placeholder properties-ref="applicationProps" />

    <task:annotation-driven />
    <task:scheduled-tasks>
        <task:scheduled ref="fileExportService" method="cronExport" cron="#{applicationProps['exportDaemon.execution.cron']}"/>
    </task:scheduled-tasks>
     -->

    <context:annotation-config />

    <tx:annotation-driven />

    <mvc:annotation-driven />


</beans>

fileExportDaemon-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:security="http://www.springframework.org/schema/security"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.1.xsd
          http://www.springframework.org/schema/tx 
          http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
          http://www.springframework.org/schema/jee 
          http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.1.3.xsd">



    <!-- Services -->
    <bean id="fileExportService" class="com.fileExportDaemon.service.FileExportService" />


</beans>

fileExportDaemon-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:security="http://www.springframework.org/schema/security"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:jee="http://www.springframework.org/schema/jee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/context 
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/tx 
          http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
          http://www.springframework.org/schema/jee 
          http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.0.3.xsd
          http://www.springframework.org/schema/mvc 
          http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.fileExportDaemon" />

    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

</beans>

FileExportService.java

package com.fileExportDaemon.service;


public class FileExportService {

    @Value("${exportDaemon.jcr.repository.url}")
    private String jcrURL;

    @Value("${exportDaemon.filesystem.separator}")
    private String filesystemSeparator;

    @Value("${exportDaemon.path.complete}")
    private String pathComplete;

    @Value("${exportDaemon.path.incomplete}")
    private String pathIncomplete;

    Log logger = LogFactory.getLog(FileExportService.class);


    public void exportFilesWithRules(){ 

        Session jcrSession = getJcrSession(jcrURL);

        try {

             Node root = jcrSession.getRootNode();
             Node dsNode = root.getNode("DS");
             Node applicationsNode= dsNode.getNode("applications");

             NodeIterator applicationNodes = applicationsNode.getNodes();


             while (applicationNodes.hasNext()) {
                    handleNode(applicationNodes.nextNode()); 
            } 

        } catch (RepositoryException e) {
            logger.error("Repository error", e);
        } 

        logger.debug("done exporting with rules!");
    }



    public void exportFilesAll(){
        logger.debug("done exporting without rules!");
    }


    private void handleNode(Node node) throws RepositoryException { 

        logger.debug(node.getPath()); 

        Node attachments = node.getNode("attachments");
        boolean isComplete = isCompleteFiling(attachments);
        if(isComplete){

            File completedEfiling = new File(pathComplete + filesystemSeparator + node.getName());

            if (!completedEfiling.exists()){
                exportNodeFiles(attachments,pathComplete);
            }else{
                logger.debug("File exists, go to next: " + node.getName());
                return;
            }

        }else{
            logger.debug("filing Incomplete!");
            File incompletedEfilingDir = new File(pathIncomplete + filesystemSeparator + node.getName());

            if(!incompletedEfilingDir.exists()){
                exportNodeFiles(attachments, pathIncomplete);
            }else if( attachments.getNodes().getSize() != incompletedEfilingDir.list().length ){
                exportNodeFiles(attachments, pathIncomplete);
            }else{
                logger.debug("files found identical on:" + node.getName());
                return;
            }

        }

        // Skip the virtual (and large!) jcr:system subtree 
        if (node.getName().equals("jcr:system")) { 
            return; 
        }
    }


    private void exportNodeFiles (Node attachmentsNode, String destinationDir){

        File directory = null;
        try {
            directory = new File(destinationDir + filesystemSeparator + attachmentsNode.getParent().getName());
        } catch (AccessDeniedException e1) {
            logger.error("Access denied error", e1);
        } catch (ItemNotFoundException e1) {
            logger.error("Item not found.", e1);
        } catch (RepositoryException e1) {
            logger.error("Repository error.", e1);
        }

        directory.mkdir();

        NodeIterator nodeIter = null;
        try {
            nodeIter = attachmentsNode.getNodes();
        } catch (RepositoryException e) {
            logger.error("Repository error.", e);
        }

        while( nodeIter.hasNext()){

            OutputStream outputStream = null;
            InputStream is = null;

            try {
                Node nodeToStore = nodeIter.nextNode().getNode("file").getNodes().nextNode();
                Node content = nodeToStore.getNodes().nextNode();

                is = content.getProperty("jcr:data").getBinary().getStream() ;

                String a = directory.getAbsolutePath() + filesystemSeparator +nodeToStore.getName();
                outputStream = new FileOutputStream(new File( directory.getAbsolutePath() + filesystemSeparator + nodeToStore.getName() ));

                int read = 0;
                byte[] bytes = new byte[1024];

                while ((read = is.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }


            } catch (PathNotFoundException e) {
                logger.error("Path not found.", e);
            } catch (RepositoryException e) {
                logger.error("Repository error.", e);
            } catch (FileNotFoundException e) {
                logger.error("File not found.", e);
            } catch (IOException e) {
                logger.error("IO error", e);
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }//finally
        }//while nodeIter has next

    }



    private boolean isCompleteFiling(Node node){
        boolean result = false;

        NodeIterator nodeIter = null;
        try {
            nodeIter = node.getNodes();
        } catch (RepositoryException e) {
            logger.error("Repository error", e);
        }

        while(nodeIter.hasNext()){

            Node attachmentNode = nodeIter.nextNode();

            try {
                if(StringUtils.endsWith(attachmentNode.getName(), ".pdf")){
                    if ( StringUtils.equals("receipt.pdf", attachmentNode.getNode("file").getNodes().nextNode().getName() )){
                        result = true;
                    }
                }else{
                    continue;
                }
            } catch (RepositoryException e) {
                logger.error("Repository error", e);
            }
        }
        return result;
    }


    private Session getJcrSession(String url){
        Repository repository = null;
        try {
            repository = JcrUtils.getRepository(url);
        } catch (RepositoryException e) {
            logger.error("Repository error", e);
        }

        SimpleCredentials creds = new SimpleCredentials("admin","admin".toCharArray());
        Session jcrSession = null;

        try {
            jcrSession = repository.login(creds, "default");
        } catch (LoginException e) {
            logger.error("could not log in to jcr", e);
        } catch (NoSuchWorkspaceException e) {
            logger.error("Could not find workspace", e);
        } catch (RepositoryException e) {
            logger.error("Repository error", e);
        }

        return jcrSession;
    }

    @Scheduled(cron="${exportDaemon.execution.cron}" )
    public void cronExport(){

        logger.debug("Starting cron export!");
        exportFilesWithRules();


    }

}

properties

exportDaemon.jcr.repository.url=http://192.168.3.3:10080/jackrabbit-webapp-2.6.2/server
exportDaemon.execution.cron=* */5 * * * *
exportDaemon.filesystem.separator=\\
exportDaemon.path.complete=C:\\files\\export\\complete
exportDaemon.path.incomplete=C:\\files\\export\\incomplete
exportDaemon.all.filings=false

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">


    <display-name>fileExportDaemon</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/application-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
      <servlet-name>fileExportDaemon</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
      <servlet-name>fileExportDaemon</servlet-name>
      <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
      <filter-name>encodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>
Was it helpful?

Solution

Just for anyone facing the same issue. I haven't found any logical solution over the described behaviour, but I have found a good work around. As said in my problem description, I have used the annotation Scheduled many times and of course it works. For this time only, I used the spring-quartz configuration and it works perfectly. The changes are not very big and you will find many many tutorials on how to use quartz with Spring. Regarding the bug, it remains a mystery. At this time, I have in fron of me two apps working with Scheduled and one with quartz. Even now I can't figure out why this happens.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top