Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Sunday, May 17, 2015

StaxEventItemWriter writes extra end document tag


I using spring batch for reading data from db and writing to XML file i am choosed the "StaxEventItemWriter" writes. it generating the xml file fine but with extra end document tag at the end. You can find the bug Here, due to this my batch process was failed to read the same XML file. I surf the internet and i found the one of the solution and  implemented the below. Now my XML files are generated without the extra end document tag. Now all my batches are working fine.

Solution:

import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;

import org.springframework.batch.item.xml.StaxEventItemWriter;

/**
 * @author sunilkumar.gutti
 * 
 */
@SuppressWarnings("rawtypes")
public class ShipmentStaxEventItemWriter extends StaxEventItemWriter {
    @Override
    protected void endDocument(XMLEventWriter writer) throws XMLStreamException {
        XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
        if (outputFactory.isPropertySupported("com.ctc.wstx.autoCloseElements")) {
            outputFactory.setProperty("com.ctc.wstx.autoCloseElements", false);
        }
    }

}

Spring batch restrict single instance of job only

I have one spring batch job which can be kicked of by rest URL. I want to make sure only one job instance is allowed to run. and if another instance already running then don't start another. even if the parameters are different.
I searched and found nothing out of box solution. thinking of extending SimpleJobLauncher. to check if any instance of the job running or not.
Answers
You could try to intercept the job execution, implementing the JobExecutionListener interface:
public class MyJobExecutionListener extends JobExecutionListener {

//active JobExecution, used as a lock.
private JobExecution _active;

public void beforeJob(JobExecution jobExecution) {
    //create a lock
    synchronized(jobExecution) {
        if(_active!=null && _active.isRunning()) {
            jobExecution.stop();
        } else {
            _active=jobExecution;
        }
    }
}

public void afterJob(JobExecution jobExecution) {
      //release the lock
      synchronized(jobExecution) {
          if(jobExecution==_active) {
            _active=null; 
          }
      }
}
}
And then, inject to the Job definition:
<job id="myJobConfig">
    <listeners>
        <listener ref="myListener"/>
    </listeners>
</job>

Or, in response to REST URL, check using JobExplorer if your job is running using job's specifics business rules

I solved this by creating an JobExecutionListner and with the help of JobExplorer I checked if any other instance is running if running then stop current job.I created listener so that it can be plugged in to any job that requires this kind of scenario.
Set<JobExecution> jobExecutions = ((SimpleJobExplorer) jobExplorer.getObject()).findRunningJobExecutions(jobExecution.getJobInstance().getJobName());
            if(jobExecutions.size()>1){
                Long currentTime = (new Date()).getTime();
                for(JobExecution execution : jobExecutions ){
                    if(execution.getJobInstance().getId().compareTo(jobExecution.getJobInstance().getId())!=0 && (currentTime - execution.getStartTime().getTime()) <lockOverideTime){
                        jobExecution.stop();
                        throw new IllegalStateException("Another instance of the job running job name : " +jobExecution.getJobInstance().getJobName() );

                    }
                }

            }

source : here

Tuesday, April 14, 2015

Weblogic (10.3.6.0): Caused by: java.lang.ClassCastException: org.eclipse.persistence.jpa.PersistenceProvider cannot be cast to javax.persistence.spi.PersistenceProvider

Problem : When performing the transaction in application (Deployed in web logic (10.3.6.0) Caused by: java.lang.ClassCastException: org.eclipse.persistence.jpa.PersistenceProvider cannot be cast to javax.persistence.spi.PersistenceProvider

Solution :

Web.xml:
 Add customer listener class to resolve the persistence provider.

<listener>
        <listener-class>com.kewill.bluedart.weblogic.POSWeblogicPresistenceListener</listener-class>
</listener>


POSWeblogicPresistenceListener.java (Customer Listener class):

package com.kewill.bluedart.weblogic;

import javax.servlet.ServletContextEvent;

public class POSWeblogicPresistenceListener implements javax.servlet.ServletContextListener {

    public void contextDestroyed(ServletContextEvent arg0) {

    }

    public void contextInitialized(ServletContextEvent arg0) {
        HibernatePersistenceProviderResolver.register();
    }
}


HibernatePersistenceProviderResolver.java (Custom Persistence provider resolver class):
package com.kewill.bluedart.weblogic;

import java.util.Collections;
import java.util.List;

import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceProviderResolver;
import javax.persistence.spi.PersistenceProviderResolverHolder;

import org.apache.log4j.Logger;
import org.hibernate.ejb.HibernatePersistence;

public class HibernatePersistenceProviderResolver implements
        PersistenceProviderResolver {
    private static final Logger LOGGER = Logger.getLogger(HibernatePersistenceProviderResolver.class.getName());

    private volatile PersistenceProvider persistenceProvider = new HibernatePersistence();

    @Override
    public List<PersistenceProvider> getPersistenceProviders() {
        return Collections.singletonList(persistenceProvider);
    }

    @Override
    public void clearCachedProviders() {
        persistenceProvider = new HibernatePersistence();
    }

    public static void register() {
        LOGGER.info("Registering HibernatePersistenceProviderResolver");
        PersistenceProviderResolverHolder
                .setPersistenceProviderResolver(new HibernatePersistenceProviderResolver());
    }
}


webloigc.xml (Weblogic delopyment descriptor):

<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.1/weblogic-web-app.xsd"
    xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
    <container-descriptor>
        <index-directory-enabled>true</index-directory-enabled>
        <prefer-application-packages>
            <package-name>antlr.*</package-name>
            <package-name>org.springframework.*</package-name>
            <package-name> org.apache.commons.*</package-name>
            <package-name>org.apache.xmlbeans.*</package-name>
            <package-name>org.hibernate.*</package-name>
            <package-name>org.hibernate.validator.*</package-name>
            <package-name>javax.persistence.*</package-name>

            <package-name>org.joda.*</package-name>
            <package-name>com.sun.xml.*</package-name>
        </prefer-application-packages>
        <prefer-application-resources>
            <resource-name>META-INF/services/javax.servlet.ServletContainerInitializer</resource-name>
            <resource-name>META-INF/spring.handlers</resource-name>
        </prefer-application-resources>
    </container-descriptor>
    <context-root>user context path</context-root>
</weblogic-web-app>


Do all the above changes. weblogic.xml : will change as per your project dependencies. No i resolved the above issue. I hope it will helps you to resolve the same.