Friday, 14 November 2014

Spring 3 Quartz - Customize quartz to refresh database on application restart

Let's say one has defined quartz jobs and triggers in Spring's context XML and want to refresh quartz tables whenever web application restarts (say for refreshing triggers), here's a way to do it -

Define your own custom QuartzSchedular bean in Spring's context XML -

<bean id="schedBean" class="com.pearson.rel.service.quartz.QuartzSchedular">
<!-- All dependencies have to be defined here. -->
<property name="schedulerContextAsMap">
<map>
<entry key="platformNotificationManager" value-ref="platformNotificationManager"/>
<entry key="platformMediaManager" value-ref="platformMediaManager"/>
</map>
</property>
<property name="triggers">
       <list>
<ref bean="platformSyncTrigger"/>
<ref bean="platformSyncArchiveTrigger"/>
       </list>
</property>
        <property name="quartzProperties">
            <props>
            <!-- Can be any string, and the value has no meaning to the scheduler itself - but rather serves as a mechanism for
            client code to distinguish schedulers when multiple instances are used within the same program. If one is using the
            clustering features, one must use the same name for every instance in the cluster that is 'logically' the same Scheduler. -->
                <prop key="org.quartz.scheduler.instanceName">Scheduler</prop>
                <!-- Can be any string, but must be unique for all schedulers working as if they are the same 'logical' Scheduler
                within a cluster. One may use the value "AUTO" as the instanceId if one wish the Id to be generated. Or the value "SYS_PROP"
                if one want the value to come from the system property "org.quartz.scheduler.instanceId". -->
                <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
                <!-- The the number of milliseconds the scheduler will 'tolerate' a trigger to pass its next-fire-time by, before being
                considered "misfired". The default value (if one don't make an entry of this property in his configuration) is 60000 (60 seconds). -->
                <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
                <!-- JDBCJobStore is used to store scheduling information (job, triggers and calendars) within a relational database.
                There are actually two seperate JDBCJobStore classes that one can select between, depending on the transactional behaviour one needs.
                JobStoreTX manages all transactions itself by calling commit() (or rollback()) on the database connection after every action
                (such as the addition of a job). JDBCJobStore is appropriate if one is using Quartz in a stand-alone application, or within a servlet
                container if the application is not using JTA transactions. -->
                <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
                <!-- Driver delegates understand the particular 'dialects' of varies database systems.  -->
                <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
                <!-- JDBCJobStore's "table prefix" property is a string equal to the prefix given to Quartz's tables that were created in the database.
                One can have multiple sets of Quartz's tables within the same database if they use different table prefixes. -->
                <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
                <!-- Set to "true" in order to turn on clustering features. This property must be set to "true" if one is having multiple instances of
                Quartz use the same set of database tables... otherwise one will experience havoc. See the configuration docs for clustering for more information. -->
                <prop key="org.quartz.jobStore.isClustered">true</prop>
                <!-- Is the name of the ThreadPool implementation one wish to use. The threadpool that ships with Quartz is "org.quartz.simpl.SimpleThreadPool", and
                should meet the needs of nearly every user. It has very simple behavior and is very well tested. It provides a fixed-size pool of threads that 'live' the lifetime of the Scheduler. -->
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <!-- Can be any positive integer, although one should realize that only numbers between 1 and 100 are very practical. This is the number of threads
                that are available for concurrent execution of jobs. If one only has a few jobs that fire  few times a day, then 1 thread is plenty! If one has tens of thousands of jobs,
                with many firing every minute, then one probably want a thread count more like 50 or 100 (this highly depends on the nature of the work that one's jobs perform, and one's systems resources!). -->
                <prop key="org.quartz.threadPool.threadCount">25</prop>
                <!-- Can be any int between Thread.MIN_PRIORITY (which is 1) and Thread.MAX_PRIORITY (which is 10). The default is Thread.NORM_PRIORITY (5). -->
                <prop key="org.quartz.threadPool.threadPriority">5</prop>
                <!-- The value of this property must be the name of one the DataSources defined in the configuration properties file. See the configuration docs for DataSources for more information. -->
                <prop key="org.quartz.jobStore.dataSource">relDS</prop>
<!-- DATASOURCE -->
<!-- Must be the java class name of the JDBC driver for the database. -->
                <prop key="org.quartz.dataSource.relDS.driver">${hibernate.connection.driver_class}</prop>
                <!-- The connection URL (host, port, etc.) for connection to the database. -->
                <prop key="org.quartz.dataSource.relDS.URL">${hibernate.connection.url}</prop>
                <!-- The user name to use when connecting to the database. -->
                <prop key="org.quartz.dataSource.relDS.user">${hibernate.connection.username}</prop>
                <!-- The password to use when connecting to the database. -->
                <prop key="org.quartz.dataSource.relDS.password">${hibernate.connection.password}</prop>
                <!-- The maximum number of connections that the DataSource can create in it's pool of connections. -->
                <prop key="org.quartz.dataSource.relDS.maxConnections">5</prop>
                <!-- Is an optional SQL query string that the DataSource can use to detect and replace failed/corrupt connections. For example an oracle user might choose "select table_name from user_tables" - which is a query that should never fail - unless the connection is actually bad. -->
                <prop key="org.quartz.dataSource.relDS.validationQuery">select 1 from dual</prop>
            </props>
      </property>
</bean>

Define the class QuartzSchedular -

public class QuartzSchedular extends SchedulerFactoryBean {
    /**
     * Logger.
     */
    private static final Log LOG = LogFactory.getLog(QuartzSchedular.class);
    /**
     * Application Context.
     */
    @Autowired
    private ApplicationContext appContxt;
    /**
     * {@inheritDoc}
     */
    public void afterPropertiesSet() {
        try {
            super.afterPropertiesSet();
        } catch (Exception e1) {
            LOG.error("Quartz not initialized: " + StringUtil.stackTraceToString(e1));
            return;
        }
        try {
            reScheduleJobs();
        } catch (SchedulerException e) {
            LOG.error("Jobs not rescheduled: " + StringUtil.stackTraceToString(e));
            return;
        }
    }
    /** Function to reschedule all the Quartz Jobs.
     * @throws SchedulerException
     */
    public void reScheduleJobs() throws SchedulerException {
        // Get schedular instance.
        Scheduler sched = getScheduler();
        //Get all the groups
        for (String group : sched.getJobGroupNames()) {
            // Get all the Jobs.
            for (String jobeName : sched.getJobNames(group)) {
                JobDetail jobDetail = sched.getJobDetail(jobeName, group);
                //Get all the triggers.
                for (Trigger trigger : sched.getTriggersOfJob(jobeName, group)) {
                    Trigger quartzTrigger = sched.getTrigger(trigger.getName(), group);
                    //Unscheduling jobs.
                    sched.unscheduleJob(trigger.getName(), group);
                    //Getting triggers from app context
                    Trigger objTrigger = (Trigger) appContxt.getBean(trigger.getName());
                    //Associating triggers with jobs.
                    sched.scheduleJob(jobDetail, objTrigger);
                }
            }
        }
    }
}

Tuesday, 11 November 2014

Spring 3 - Create tests with MockWebApplication and MockWebApplicationContextLoader

Ok lets say one has to test his custom exception handler which he has defined in Spring 3, here is a way to do it :-

Define custom exception handler "APIExceptionHandler" -
public class APIExceptionHandler implements HandlerExceptionResolver {

    public ModelAndView resolveException(final HttpServletRequest request,final HttpServletResponse response, final Object handler, final Exception exception) {
    /**
     * return ModelAndView based on exception
    */

    }
}
Now create interface MockWebApplication:-

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MockWebApplication {
	/**
	 * The location of the webapp directory relative to your project.
	 * For maven users, this is generally src/main/webapp (default).
	 */
	String webapp() default "/web";
	/**
	 * The servlet name as defined in the web.xml.
	 */
	String name();
}

Create MockWebApplicationContextLoader as below:-

public class MockWebApplicationContextLoader extends AbstractContextLoader {
	/**
	 * The configuration defined in the {@link MockWebApplication} annotation.
	 */
	private MockWebApplication configuration;
	@SuppressWarnings("serial")
	public ApplicationContext loadContext(String... locations) throws Exception {
		// Establish the servlet context and config based on the test class's MockWebApplication annotation.
		final MockServletContext servletContext = new MockServletContext(new FileSystemResourceLoader());
		final MockServletConfig servletConfig = new MockServletConfig(servletContext, configuration.name());
		// Create a WebApplicationContext and initialize it with the xml and servlet configuration.
		final XmlWebApplicationContext webApplicationContext = new XmlWebApplicationContext();
		servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);
		webApplicationContext.setServletConfig(servletConfig);
		webApplicationContext.setConfigLocations(locations);
		// Create a DispatcherServlet that uses the previously established WebApplicationContext.
		final DispatcherServlet dispatcherServlet = new DispatcherServlet() {
			protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
				return webApplicationContext;
			}
		};
		dispatcherServlet.setDetectAllHandlerMappings(true);
		final APIExceptionHandler aPIExceptionHandler = new APIExceptionHandler();
		// Add the DispatcherServlet (and anything else you want) to the context.
		// Note: this doesn't happen until refresh is called below.
		webApplicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
			public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
				beanFactory.registerResolvableDependency(DispatcherServlet.class, dispatcherServlet);
			beanFactory.registerResolvableDependency(HandlerExceptionResolver.class, aPIExceptionHandler);
				// Register any other beans here, including a ViewResolver if you are using JSPs.
			}
		});
		// Have the context notify the servlet every time it is refreshed.
		webApplicationContext.addApplicationListener(new SourceFilteringListener(webApplicationContext, new ApplicationListener<ContextRefreshedEvent>() {
			public void onApplicationEvent(ContextRefreshedEvent event) {
				dispatcherServlet.onApplicationEvent(event);
			}
		}));
		// Prepare the context.
		webApplicationContext.refresh();
		webApplicationContext.registerShutdownHook();
		// Initialize the servlet.
		dispatcherServlet.setContextConfigLocation("");
		dispatcherServlet.init(servletConfig);
		return webApplicationContext;
	}
	/**
	 * One of these two methods will get called before {@link #loadContext(String...)}.
	 * We just use this chance to extract the configuration.
	 */
	protected String[] generateDefaultLocations(Class<?> clazz) {
		extractConfiguration(clazz);
		return super.generateDefaultLocations(clazz);
	}
	/**
	 * One of these two methods will get called before {@link #loadContext(String...)}.
	 * We just use this chance to extract the configuration.
	 */
	protected String[] modifyLocations(Class<?> clazz, String... locations) {
		extractConfiguration(clazz);
		return super.modifyLocations(clazz, locations);
	}
	private void extractConfiguration(Class<?> clazz) {
		configuration = AnnotationUtils.findAnnotation(clazz, MockWebApplication.class);
		if (configuration == null)
			throw new IllegalArgumentException("Test class " + clazz.getName() + " must be annotated @MockWebApplication.");
	}
	protected String getResourceSuffix() {
		return "-context.xml";
	}
}

Friday, 7 November 2014

TestNG parameterized test using XLS and test data model

Lets say there is a XLS file with test data in following format:-

UserName
Password
Email
abcP1abc@gmail.com
xyzP2xyz@gmail.com

Create model for the above XLS:-

public class TestModel {
       private String userName,password,eMail;
       public TestModel (Object[] column){
  userName = (String)column[0];
  password = (String)column[1];
  eMail= (String)column[2];
 }
      /* 
         Getters here...
     */
}

Create parameterized test:-

@Test(dataProvider = "xlsReader")
public void parameterizedTest(TestModel testModel ) throws Exception {
      /* 
        Perform test using model
     */
}

Create data provider:-

@DataProvider
public static Object[][] xlsReader() throws Exception {
       return SpreadsheetReader.getXlsData("XLS_FILE", TestModel.class);
}

Tuesday, 16 October 2012

Connect to Firepass VPN on Linux without a browser


The Python script, to connect to Firepass VPN without a client, developed by James Knight can be downloaded from: http://fuhm.net/software/f5vpn-login/
Download all the files at the above location in a directory (lets call it firepass directory).
The script requires Python version greater than 2.3.5

  
 Steps to install Python (Version greater than 2.3.5)
  • Login as root user
  • Open command prompt and type “yum install python”. This will install default version of python as per repository of the machine. Make sure the version is greater than 2.3.5
  • Type yes if it asks for confirmation
  •  Make sure “ppp” is installed on machine by typing “rpm -qa | grep ppp”. It will show version, if nothing appears then ppp is not installed. Install it by typing “yum install ppp”.
  • Make sure firewall doesn’t block port 2401 (for CVS)

  In case the make file given with the Python script does not work, follow the step below:-
  • Open terminal window and goto firepass directory
  • Type “gcc -DPYTHON=\"/usr/bin/python\" -DPREFIX=\"/usr\" -o f5vpn-login-runner f5vpn-login-runner.c”
  • Type “cp f5vpn-login.py /usr/sbin/f5vpn-login.py”
  • Type “cp f5vpn-login-runner /usr/bin/f5vpn-login”
  • Type “chmod u+s /usr/bin/f5vpn-login”
  • This will install firepass vpn connection script.   
  • To connect to vpn type “f5vpn-login user@host”.  
  • In case you want to run it in background type “f5vpn-login user@host &”.  

The scripts works beautifully, thanks to James Knight for developing it :)