Interest of a buffering system

A captcha (picture or sound) needs a lot of computing time comparing to the time usually required to generate a web page. The more captchas are hard to crack by computers, the more it takes time to create.

Conceptual solution

Pre generating captcha can prevent web site overloading. Considering the need, there is two possible solutions:

The JCaptcha buffering system implements the two solutions with

Technical solution

A component, BufferedEngineContainer, which implements the CaptchaEngine interface, produces captchas through a normal captcha engine.

It uses two buffers; one to store captchas in a persistent way, implementation of this buffer is either a file buffer on disk, or a database. Another buffer is used to quickly deliver captchas; this is implemented with a RAM buffer, like a stack, or a list.

The BufferedEngineContainer component has two main operations:

These operations are controlled by timing components. JCaptcha provide implementations of timing components :

At least but not last, a management component provided real time control on the Quartz implementation:

Setting the Captcha buffering system in Spring

The captcha buffering system can be configured the same way as Captcha Engines, but it can be less explicit as not all components are part of JCaptcha.

Some Spring configuration files are available as testing resources

The first root component is the BufferedEngineContainer, which feed a persistent buffer and swap captchas from this buffer to a volatile buffer. So to build this component you need :

<bean class="com.octo.captcha.engine.bufferedengine.QuartzBufferedEngineContainer" id="imageContainer" singleton="true">

	<constructor-arg type="com.octo.captcha.engine.CaptchaEngine" index="0"><ref bean="imageEngine"/></constructor-arg>

	<constructor-arg type="com.octo.captcha.engine.bufferedengine.buffer.CaptchaBuffer" index="1"><ref bean="imageMemBuffer"/></constructor-arg>

	<constructor-arg type="com.octo.captcha.engine.bufferedengine.buffer.CaptchaBuffer" index="2"><ref bean="imagePersistantBuffer"/></constructor-arg>

	<constructor-arg type="com.octo.captcha.engine.bufferedengine.ContainerConfiguration" index="3"><ref bean="imageConfiguration"/></constructor-arg>

</bean>

The ContainerConfiguration sets:

  1. The map of ratio corresponding to locales
  2. The maximal size of the volatile buffer
  3. The maximal size of the persistent buffer
  4. The size of the swap
  5. The size of the feed
  6. The Boolean to know if the container only serves configured locales
  7. The Default local to use
    <bean id="imageConfiguration" class="com.octo.captcha.engine.bufferedengine.ContainerConfiguration">
    
    	<constructor-arg index="0">
    		<map>
    			<entry key-ref="java.util.Locale.FRENCH" value-ref="ratioFR"/>
    		</map>
    	</constructor-arg>
    	<\!--memory size-->
    	<constructor-arg index="1"><value>1000</value></constructor-arg>
    	<\!--persistent size-->
    	<constructor-arg index="2"><value>100000</value></constructor-arg>
    	<\!--swap size-->
    	<constructor-arg index="3"><value>1000</value></constructor-arg>
    	<\!--feed size-->
    	<constructor-arg index="4"><value>100000</value></constructor-arg>
    	<\!--feed batch size-->
    	<constructor-arg index="5"><value>100</value></constructor-arg>
    	<\!--Serve only configured locales?-->
    	<constructor-arg index="6"><value>true</value></constructor-arg>
    	<\!--default locale to serve-->
    	<constructor-arg index="7"><ref bean="java.util.Locale.FRENCH"/></constructor-arg>
    
    </bean>
    
    And the declaration of the map of ratio corresponding to locales uses :
    <bean id="java.util.Locale.FRENCH" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
    
    <bean id="ratioFR" class="java.lang.Double">
    	<constructor-arg index="0"><value>1.0</value></constructor-arg>
    </bean>
    
    Next we define buffers, the volatile buffer is simple:
    <bean class="com.octo.captcha.engine.bufferedengine.buffer.MemoryCaptchaBuffer" id="imageMemBuffer">
    </bean>
    
    The persistant buffer can be more complex, the following sample use a database implementation, with a data source:
<bean class="com.octo.captcha.engine.bufferedengine.buffer.DatabaseCaptchaBuffer" id="imagePersistantBuffer">
	<constructor-arg index="0"><ref bean="dataSource"/></constructor-arg>

	<!--table name-->
	<constructor-arg type="java.lang.String" index="1"><value>jcaptcha_t</value></constructor-arg>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" singleton="true">
	<property name="driverClassName">
		<value>org.hsqldb.jdbcDriver</value>
	</property>
	<property name="url">
		<value>jdbc:hsqldb:jcaptchaDB</value>
	</property>
	<property name="username">
		<value>jcaptcha</value>
	</property>
	<property name="password">
		<value>jcaptcha</value>
	</property>
</bean>

The next part is about Quartz, the scheduling framework.
We first define a Scheduler, which: