About

Jadira is the home for Sousan and Chris Pheby's open source projects. These are reusable open source Java modules that provide first class solutions using the most effective current JEE technologies.

Search
Tag Cloud
...
Login
Monday
Apr212014

Batching Transactions for Performance with Spring

We all know that JTA is slow, right? Not so fast, a key issue with JTA in a messaging environment is that we are applying a transaction once per message. The theme of this post is the implementation of transactional batching, another problem I've faced and resolved many times over the course of about a decade.

Significant performance benefits can be realised with many messaging providers such as ActiveMQ and WebSphereMQ and these can be achieved without sacrificing the reliability of the end application.

For a bit of context here's an extract from an existing article on this subject:

Should you forgo JMSTemplate and batch everything? Well, as with pretty much anything, it depends.

JMSTemplate is simple to configure and use – it also ties in nicely to the various Spring abstractions (TransactionManagers come to mind). There are certainly some upsides to getting down to the JMS API, however they come at a cost of time coding and losing those hooks; which you might regret later.

Batching itself is a funny one, in that it’s one of those things that could be easily misused. Transactions are not there for improving performance. They exist as a logical construct for making atomic changes. If you batch up messages in memory to send to the broker for a performance upshot that are unrelated; and your container goes down before you’ve had a chance to commit; you have violated the contract of “this business action has been completed”, and you lost your messages. Not something you want for important, change-the-world messages.

If you have messages that are relatively unimportant that won’t affect the correct operation of your system, there are better options available to you for improving performance such as dropping persistence.

If, however, you have related messages tied to a single operation, then perhaps getting down to the JMS API and batching these together under a single transaction is something you might want to consider. The key here is ensuring that you don’t lose the real meaning of transaction.

Jakub Korab, Batching JMS messages for performance; not so fast

Now for the surprising part - you don't have to forgo Spring's JMSTemplate and DefaultMessageListenerContainer to get transactional batching. Jadira JMS introduces specialisations of these classes that support transactional batching within the familiar Spring programming model.

Transactional Batching with BatchedMessageListenerContainer

BatchedMessageListenerContainer customises DefaultMessageListenerContainer to support transactional batching. What this means in practice is that up to n messages can be configured to be read and processed within each transaction. You can use this class as a drop-in replacement for DefaultMessageListenerContainer.

It does provide some additional properties to configure. Firstly you should wire in a transactionManager instance using the existing setter. Secondly, the batchSize property should be configured to an appropriate value (it defaults to 150). Two additional properties - retryMitigation and concludeBatchOnRedeliveredMessage - control error mitigation and attempt to reduce the batch size when errors are encountered. It is recommended to leave these enabled unless you are certain they will not be required.

With the container configured you are now ready to use it. An important factor to be aware of is that you should avoid rollback for errors that can be identified and handled appropriately within the application. For example, a badly formed message should be delivered to an error queue, rather than relying on rollback. This will help ensure one bad message doesn't roll back the entire application. Jadira provides a base class you can extend in your Message Driven Pojos to assist with this (see below).

If you are interested in how this class works, be aware that the key functionality lies in a customised implementation of doReceiveAndExecute. Here is the key code segment:

            messages = new ArrayList<Message>();

            message = receiveMessage(consumer);
            if (message != null) {

                messages.add(message);
                ...
            } ...

            int count = 0;

            ...
            while ((message != null) && (++count < maxMessagesPerTransaction) ...) {
               
                message = receiveMessageNoWait(consumer);

                if (message != null) {
                    messages.add(message);
                    ...
                } ...
            }

Transactional Batching with BatchedJMSTemplate

BatchedMessageListenerContainer is good for the event driven style, but in certain circumstances you want access to a polling batching capability. For this purpose, BatchedJmsTemplate is also supplied. This class extends JmsTemplate and adds additional methods equivalent to the existing methods but that perform batch operations. A setter allows configuration of the batch size - this can also be specified on a message basis. Like BatchedMessageListenerContainer the transaction manager should be injected into the class.

AbstractMessageDriven

AbstractMessageDriven is a base class that can be used when implementing MessageDrivenPojos (MDPs). It provides an error handling pattern that allows messages in error to be routed direct to an error queue with error information and JMS Headers preserved.

Simply subclass implementing doOnMessage (rather than onMessage) and inject in a JmsTemplate for delivering messages to an error queue. To trigger delivery to an error queue, simply throw Fatal JmsException from within your doOnMessage method.

The stack trace and exception message will be preserved in the message properties cause_exceptionMessage and cause_exceptionStackTrace. Other JMS Headers and JMS Properties will be preserved with the prefix 'original_' - the CorrelationID and Priority will remain on the message. The error payload will be the original message that caused the error.

This class works particularly well in conjunction with the BatchedMessageListenerContainer and BatchedJmsTemplate where it mitigates the likelihood of rollback from errors in message processing.

These classes are in GitHub - I welcome your feedback as ever.

Unit Testing with ActiveMQ

By combining ActiveMQ and JBoss Transactions we can develop message driven code with fully transactional behaviour - out of container.

The approach fits very well with the JPA configuration described in the previous blog post - they make perfect partners. Here's an example of the necessary Spring configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:amq="http://activemq.apache.org/schema/core"
    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.xsd
                        http://activemq.apache.org/schema/core
                        http://activemq.apache.org/schema/core/activemq-core.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- Transaction Manager to use -->
    <bean id="jbossTransactionManager"
        class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple">
        <property name="transactionTimeout" value="300" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <ref bean="jbossTransactionManager" />
        </property>
        <property name="allowCustomIsolationLevels" value="true" />
    </bean>

    <!-- Embedded ActiveMQ Broker -->
    <amq:broker id="activeMQBroker" useJmx="false" persistent="false">
        <amq:transportConnectors>
            <amq:transportConnector uri="tcp://localhost:43232" />
        </amq:transportConnectors>
    </amq:broker>

    <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory"
        depends-on="activeMQBroker">
        <property name="brokerURL"
            value="tcp://localhost:43232?jms.redeliveryPolicy.maximumRedeliveries=1" />
    </bean>

    <bean id="jmsConnectionFactory"
        class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="activeMQConnectionFactory" />
        <property name="sessionCacheSize" value="2" />
    </bean>

    <!-- ActiveMQ destinations to use -->
    <amq:queue id="testDestination" physicalName="org.jadira.jms.test" />

    <!-- Example Listener -->
    <bean id="testMessageListener" class="org.jadira.jms.container.TestMessageListener" />

    <!-- The Container -->
    <bean id="messageListenerContainer"
        class="org.jadira.jms.container.BatchedMessageListenerContainer">
        <property name="connectionFactory" ref="jmsConnectionFactory" />
        <property name="destinationName" value="testDestination" />
        <property name="messageListener" ref="testMessageListener" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="exceptionListener" ref="jmsConnectionFactory" />
        <property name="concurrency" value="2-5" />
        <property name="maxMessagesPerTransaction" value="100" />
    </bean>

</beans>

Saturday
Apr192014

Spring, Hibernate and JTA - A Better Integration

The Problem Space

A perennial issue I have frequently encountered (and solved) lies in the integration of Spring and Hibernate's transaction management.

Both Spring and Hibernate provide distinct transaction manager lookup strategies. In Spring, you'll typically configure a transaction manager by declaring a Spring managed bean that implements the PlatformTransactionManager interface provided by Spring. Included with Spring are a variety of implementations for the most common application servers as well as some non-JTA implementations, that are suitable for testing or limited (single-resource) production uses.

Meanwhile, Hibernate provides its abstraction - the JtaPlatform, the implementing type for which must be configured as part of the Hibernate EntityManager or Session configuration.

The result is that for each deployment environment - unit test, and any planned production container - a separate transaction manager and entity manager must be configured. As an additional problem, if you want to use local transactions in unit tests, the type (JTA or RESOURCE_LOCAL) must be changed in the persistence.xml.

All of this means, that delivery of portable components is fraught with complexity and configuration hell.

A Simplification

A huge simplification could be gained if Hibernate could reference whatever transaction manager you configured in Spring. The Hibernate API requires the capability to access the JTA Transaction Manager, and Spring can provide this - assuming you configured a JtaTransactionManager or one ifs subclasses, which expose both getTransactionManager and getUserTransaction methods.

Assuming we could provide to Hibernate the JtaTransactionManager, we can write an implementation of AbstractJtaPlatform which looks up the resources we need:

    @Override
    protected TransactionManager locateTransactionManager() {
        return transactionManager.getTransactionManager();
    }

    @Override
    protected UserTransaction locateUserTransaction() {
        return transactionManager.getUserTransaction();
    }

Customising LocalContainerEntityManagerFactoryBean

Providing the TransactionManager to this class is tricky. That is because its lifecycle and instantiation is managed by Hibernate, not by Spring. However, assuming you are using Spring to bootstrap the Hibernate Session or EntityManager, the solution is relatively straightforward. I'll discuss the EntityManager case - the Session solution is essentially the same.

It becomes necessary to subclass LocalContainerEntityManagerFactoryBean, and include on the subclass a setter allowing injection of the Spring TransactionManager. Then, the createNativeEntityManagerFactory() method needs overriding:

public class HibernateEntityManagerFactoryBean extends LocalContainerEntityManagerFactoryBean {

    private JtaTransactionManager transactionManager;

    private static final ThreadLocal<JtaTransactionManager> configurationTransactionManagerHolder = new ThreadLocal<JtaTransactionManager>();

    static JtaTransactionManager getConfigurationTransactionManager() {
        return configurationTransactionManagerHolder.get();
    }

    @Override
    protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException {

        if (this.transactionManager != null) {
            configurationTransactionManagerHolder.set(this.transactionManager);
        }

        try {
            return super.createNativeEntityManagerFactory();
        } finally {

            if (this.transactionManager != null) {
                configurationTransactionManagerHolder.set(null);
            }
        }
    }

    /**
     * Associate a transaction manager with this session
     * @param transactionManager The {@link JtaTransactionManager}
     */
    public void setTransactionManager(JtaTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }
}

As Hibernate is bootstrapped, the JtaTransactionManager reference is stored in a static ThreadLocal. We use ThreadLocal to guard against the possibility of Spring being bootstrapped in other threads within the same classloader - at the same time (e.g. within an application server). This ThreadLocal can then be accessed via our JtaPlatform implementation as it initialises. Here's the full code for that:

public class LocalTransactionManagerPlatform extends AbstractJtaPlatform implements JtaPlatform {

    private static final long serialVersionUID = 8676743510117311360L;

    private volatile JtaTransactionManager transactionManager;

    public LocalTransactionManagerPlatform() {

        JtaTransactionManager tm = HibernateEntityManagerFactoryBean.getConfigurationTransactionManager();
        if (tm == null) {
            tm = HibernateSessionFactoryBean.getConfigurationTransactionManager();
        }

        if (tm == null) {
            throw new IllegalStateException(
                    "No JTA TransactionManager found - "
                            + "'hibernate.transaction.jta.platform' property must be set on the containing LocalSessionFactoryBean or LocalEntityManagerFactoryBean as appropriate");
        }

        this.transactionManager = tm;
    }

We've solved the integration part. So now we only need configure the EntityManager using our specialised subclass, injecting the transaction manager into it, and configuring our JtaPlatform as a Hibernate property. The configuration is completely portable - we just need to change the specification of our transaction manager bean.

Unfriendly Containers

Some containers (one in particular) stand out as being unfriendly to this strategy because although they implement JtaTransactionManager as part of the Spring provided class, their getTransactionManager()  method doesn't return anything meaningful. IBM's WebSphere is the standout example as they fulfill the JTA contracts in Spring using the proprietary Unit Of Work API. To get this environment working with our approach we need to extend the Spring provided class to return a valid transaction manager instance. What we actually will do is return an adapter that fulfills (enough) of the JTA API by delegating to the WebSphere Unit of Work API. A pure Hibernate solution for this is documented at itdevworld. Its straightforward to adapt this approach by subclassing WebSphereUowTransactionManager. Here's the code:

public class SpringWebSphereUowTransactionManager extends WebSphereUowTransactionManager {

    private static final long serialVersionUID = 4838070722625854290L;

    private static final String UOW_SYNCHRONIZATION_REGISTRY_JNDINAME = "java:comp/websphere/UOWSynchronizationRegistry";
    private static final String USER_TRANASCTION_JNDINAME = "java:comp/UserTransaction";

    private static final Field UOW_FIELD;

    static {
        try {
            UOW_FIELD = WebSphereUowTransactionManager.class.getDeclaredField("uowManager");
            UOW_FIELD.setAccessible(true);
        } catch (SecurityException e) {
            throw new IllegalStateException(
                    "Not permitted to access WebSphereUowTransactionManager: " + e.getMessage(), e);
        } catch (NoSuchFieldException e) {
            throw new IllegalStateException("Could not find WebSphereUowTransactionManager: " + e.getMessage(), e);
        }
    }

    /**
     * Creates a new instance
     */
    public SpringWebSphereUowTransactionManager() {
        super();
    }

    @Override
    public void afterPropertiesSet() throws TransactionSystemException {
        super.afterPropertiesSet();
        setTransactionManager(new TransactionManagerAdapter(getJndiTemplate(), retrieveUowManager()));
        setUserTransactionName(USER_TRANASCTION_JNDINAME);
    }

    private Object retrieveUowManager() {
        try {
            Object uowManager = UOW_FIELD.get(this);
            return uowManager;
        } catch (SecurityException e) {
            throw new IllegalStateException(
                    "Not permitted to access WebSphereUowTransactionManager: " + e.getMessage(), e);
        } catch (IllegalArgumentException e) {
            throw new IllegalStateException("Unexpected argument accessing WebSphereUowTransactionManager: "
                    + e.getMessage(), e);
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception accessing WebSphereUowTransactionManager: "
                    + e.getMessage(), e);
        }
    }

    /**
     * An adapter that fulfils the JTA {@link TransactionManager} by delegating to the WebSphereUOWTransactionManager
     */
    public static class TransactionManagerAdapter implements TransactionManager {

        private final JndiTemplate jndiTemplate;

        private final Object uowManager;
        private final Class<?> uowManagerClass;

        private final Object uowSynchronizationRegistry;
        private final Class<?> uowSynchronizationRegistryClass;

        private final Method registerSynchronizationMethod;
        private final Method setRollbackOnlyMethod;

        private final Class<?> extendedJTATransactionClass;
        private final Method getLocalIdMethod;

        /**
         * Create a new instance
         * @param jndiTemplate An instance of Spring's JndiTemplate to use to look up resources
         * @param uowManager UOWManager to use
         */
        private TransactionManagerAdapter(JndiTemplate jndiTemplate, Object uowManager) {

            try {
                this.uowManagerClass = Class.forName("com.ibm.ws.uow.UOWManager");

                this.uowSynchronizationRegistry = jndiTemplate.lookup(UOW_SYNCHRONIZATION_REGISTRY_JNDINAME);
                this.uowSynchronizationRegistryClass = Class
                        .forName("com.ibm.websphere.uow.UOWSynchronizationRegistry");

                this.registerSynchronizationMethod = uowSynchronizationRegistryClass.getMethod(
                        "registerInterposedSynchronization", new Class[] { Synchronization.class });
                this.setRollbackOnlyMethod = uowManagerClass.getMethod("setRollbackOnly", new Class[] {});

                this.extendedJTATransactionClass = Class
                        .forName("com.ibm.websphere.jtaextensions.ExtendedJTATransaction");
                this.getLocalIdMethod = extendedJTATransactionClass.getMethod("getLocalId", (Class[]) null);

            } catch (ClassNotFoundException e) {
                throw new IllegalStateException("Could not find required WebSphere class: " + e.getMessage(), e);
            } catch (NoSuchMethodException e) {
                throw new IllegalStateException("Could not find required method: " + e.getMessage(), e);
            } catch (NamingException e) {
                throw new IllegalStateException("Problem accessing JNDI: " + e.getMessage(), e);
            }

            this.jndiTemplate = jndiTemplate;
            this.uowManager = uowManager;
        }

        @Override
        public void begin() {
            throw new UnsupportedOperationException("begin() is not supported");
        }

        @Override
        public void commit() {
            throw new UnsupportedOperationException("commit() is not supported");
        }

        @Override
        public int getStatus() {
            throw new UnsupportedOperationException("getStatus() is not supported");
        }

        @Override
        public void resume(Transaction txn) {
            throw new UnsupportedOperationException("resume() is not supported");
        }

        @Override
        public void rollback() {
            throw new UnsupportedOperationException("rollback() is not supported");
        }

        @Override
        public void setTransactionTimeout(int i) {
            throw new UnsupportedOperationException("setTransactionTimeout() is not supported");
        }

        @Override
        public Transaction suspend() {
            throw new UnsupportedOperationException("suspend() is not supported");
        }

        @Override
        public void setRollbackOnly() throws IllegalStateException {
            try {
                setRollbackOnlyMethod.invoke(uowManager, new Object[] {});
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("Could not access setRollbackOnly() on UOWManager: " + e.getMessage(),
                        e);
            } catch (InvocationTargetException e) {
                throw new IllegalStateException("Could not invoke setRollbackOnly() on UOWManager: " + e.getMessage(),
                        e);
            }
        }

        @Override
        public Transaction getTransaction() {
            return new TransactionAdapter(jndiTemplate);
        }

        /**
         * An adapter that fulfils the JTA transaction interface.
         */
        public class TransactionAdapter implements Transaction {

            private final Object extendedJTATransaction;

            /**
             * Creates a new instance
             * @param template The JndiTemplate
             */
            private TransactionAdapter(JndiTemplate template) {
                try {
                    extendedJTATransaction = template.lookup("java:comp/websphere/ExtendedJTATransaction");

                } catch (NamingException e) {
                    throw new IllegalStateException("Could not find ExtendedJTATransaction in JNDI: " + e.getMessage(),
                            e);
                }
            }

            @Override
            public void registerSynchronization(final Synchronization synchronization) {

                try {
                    registerSynchronizationMethod.invoke(uowSynchronizationRegistry, new Object[] { synchronization });
                } catch (IllegalArgumentException e) {
                    throw new IllegalStateException("Unexpected argument accessing UOWSynchronizationRegistry: "
                            + e.getMessage(), e);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Unexpected exception accessing UOWSynchronizationRegistry: "
                            + e.getMessage(), e);
                } catch (InvocationTargetException e) {
                    throw new IllegalStateException(
                            "Could not invoke registerSynchronization() on UOWSynchronizationRegistry: "
                                    + e.getMessage(), e);
                }
            }

            @Override
            public void commit() {
                throw new UnsupportedOperationException("commit() is not supported");
            }

            @Override
            public boolean delistResource(XAResource resource, int i) {
                throw new UnsupportedOperationException("delistResource() is not supported");
            }

            @Override
            public boolean enlistResource(XAResource resource) {
                throw new UnsupportedOperationException("enlistResource() is not supported");
            }

            @Override
            public int getStatus() {
                if (0 == getLocalId()) {
                    return Status.STATUS_NO_TRANSACTION;
                } else {
                    return Status.STATUS_ACTIVE;
                }
            }

            @Override
            public void rollback() throws IllegalStateException, SystemException {
                throw new UnsupportedOperationException("rollback() is not supported");
            }

            @Override
            public void setRollbackOnly() {
                try {
                    setRollbackOnlyMethod.invoke(uowManager, new Object[] {});
                } catch (IllegalArgumentException e) {
                    throw new IllegalStateException("Unexpected argument accessing UOWManager: " + e.getMessage(), e);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Unexpected exception accessing UOWManager: " + e.getMessage(), e);
                } catch (InvocationTargetException e) {
                    throw new IllegalStateException("Could not invoke setRollbackOnly() on UOWManager: "
                            + e.getMessage(), e);
                }
            }

            @Override
            public int hashCode() {
                return getLocalId();
            }

            @Override
            public boolean equals(Object other) {
                if (!(other instanceof TransactionAdapter))
                    return false;
                TransactionAdapter that = (TransactionAdapter) other;
                return getLocalId() == that.getLocalId();
            }

            private int getLocalId() {
                try {
                    return ((Integer) (getLocalIdMethod.invoke(extendedJTATransaction, (Object[]) null))).intValue();
                } catch (IllegalArgumentException e) {
                    throw new IllegalStateException("Unexpected argument accessing ExtendedJTATransaction: "
                            + e.getMessage(), e);
                } catch (IllegalAccessException e) {
                    throw new IllegalStateException("Unexpected exception accessing ExtendedJTATransaction: "
                            + e.getMessage(), e);
                } catch (InvocationTargetException e) {
                    throw new IllegalStateException("Could not invoke getLocalId() on ExtendedJTATransaction: "
                            + e.getMessage(), e);
                }
            }

        }
    }
}

Unit Testing

I've still not discussed how unit testing can be performed with JTA. In the past this used to be quite tricky, but now its straightforward using JBoss Narayana (formerly JBoss Transactions, formely Arjuna).

Narayana needs to be added as a test build dependency:

            <dependency>
                <groupId>org.jboss.narayana.jta</groupId>
                <artifactId>narayana-jta</artifactId>
                <version>5.0.1.Final</version>
                <scope>test</scope>
            </dependency>

 And the Spring Transaction manager that uses Narayana needs to be declared:

<bean id="jbossTransactionManager" class="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple">
        <property name="transactionTimeout" value="300" />
    </bean>

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <ref bean="jbossTransactionManager" />
        </property>
        <property name="allowCustomIsolationLevels" value="true" />
    </bean>

The configuration is ready for Unit Testing.

I've had to solve this problem many times - I hope the solution is useful.

You'll find the full code in the usertype.spi module in the package org.jadira.usertype.spi.jta. Do let me know if you can suggest improvements or find problems with it.

Saturday
Apr192014

Classes for IO

Jadira 3.2.0.GA will introduce some new classes for IO as part of a jadira-lang module. See JDF-77.

These address adapting NIO and traditional Java IO streams, optimised Buffered Stream inplementations, and an extension of the SAX InputSource that supports a variety of Source providers including the Spring Resource abstraction.

IO2NIO

This package provides two classes. ByteBufferBackedOutputStream is a custom OutputStream that writes to a ByteBuffer. ByteBufferBackedInputStream exposes reading from a ByteBuffer via an InputStream.

Core

I have frequently had the need to create similar classes to this one, so its well overdue to include it into Jadira. The class is a subclass of SAXInputSource. Its key feature is the variety of types from which the InputSource can be constructed - constructors are provided for File, InputStream, InputStreamSource, Resource (from Spring Framework) and URL.

Buffered

This package provides classes intended to be be used as an alternative to BufferedInputStream and BufferedOutputStream. Unlike those JDK classes they do not provide synchronization of their methods.

The following classes are provided for InputStream capabilities:

AbstractBufferedInputStream provides base functionality. It recreates some functionality from BufferedInputStream, but is organised to facilitate extendability. Whilst it does not subclass BufferedInputStream it instead subclasses FilterInputStream (the superclass of BufferedInputStream), so can be used in many of the same places.

Three subclasses exist, these are backed by DirectByteBuffer, ByteBuffer and a byte array respectively.

For OutputStream, equivalent buffered classes are provided with similar properties:

Monday
Apr072014

Fixing Netflix Errors N8156-6013 and N8156-6023 with Firefox

I've been scratching my head on this for a while. The error occurred with Firefox 28 and Silverlight 5. Reinstalls, clearing session, deleting C:\ProgramData\Microsoft\PlayReady\mspr.hds all did nothing.

The working solution was straightforward in the end:

  1. Run C:\Program Files\Microsoft Silverlight\5.1.30214.0\Silverlight.Configuration.exe, then click on 'Application Storage' and 'Delete All'. Ensure 'Enable Application Storage' is left ticked.
  2. Close all browsers then navigate to C:\ProgramData\Microsoft\PlayReady and delete mspr.hds.
  3. Right-click the Firefox taskbar icon, then right-click on 'Mozilla Firefox' and choose 'Run As Administrator'.
  4. Once Firefox is launched, select 'Help' and 'Restart with Add-ons Disabled'.
  5. When Firefox launches, select 'Safe Mode' and wait for Firefox to launch.
  6. Browse to Netflix and watch a film.
  7. Close Firefox and restart it.

I hope this helps anyone else getting the same issue.

 

Tuesday
Mar112014

Announcing Jadira 3.1.0.GA

I’ve just released Jadira 3.1.0.GA. Its currently being promoted to Maven Central so may be a few hours before it shows up there.

This release follows nearly a year and half since our last stable release (3.0.0.GA) and eleven candidate releases. It is definitely time for the GA release, with many users tracking the CR releases which now significantly exceed 3.0.0 in usage.

Everyone using 2.0.x and 3.0.x should now be thinking of upgrading.

In 3.1.0 there are significant new features, evolution to existing capabilities and a significant strengthening to the codebase.

Key features in this release include:

Usertype

  • Support for:
    • JSR310 (Java 8)
    • ThreeTen Backport
    • Joda Time
    • Legacy JDK Temporal types
    • Joda Money
    • JDK Enums
    • Libphonenumber (uses Jadira’s cdt – common data types module)
    • ISO Country Codes (uses Jadira’s cdt – common data types module)
  • New Timezone managing algorithm. Especially MySQL users need to pay attention as they now need to set the JDBC connection property 'useLegacyDatetimeCode=false'
  • Global configuration options reduce domain verbosity. These exist for type auto-registration, java and database timezones, default currency codes and sequence generation seeds.
  • Typesafe, plumbing free and multiple-tier friendly JPA repositories.

Documentation has also been improved with (almost) comprehensive Javadoc and an enhanced (if still terse) user guide for the Usertypes modules at http://jadira.sourceforge.net/usertype-userguide.html.

Cloning

  • The first release for a high performance object cloning library with ASM, Reflection, InvokeDynamic and sun.misc.Unsafe based access strategies. Cloning introduces variants on the commons-lang HashCodeBuilder and EqualsBuilder that take advantage of the object access strategies. Cloning can be integrated with Orika to provide a cloning converter as part of a larger transformation.

Bindings

  • Extensible framework for registering and invoking conversions of objects from one class to another

Scanner

  • A multi-threaded library for classpath inspection in the spirit of Scannotation.

I’ll be continuing to add to the documentation for the various moules with successive releases.

Jadira aims to deliver the building blocks for domain driven applications that perform well with minimal code and a rich type safe model. As Jadira moves towards the next release I’ll be working on extending the features with more tooling that supports building rich domains that integrate well with the event driven style.

 As usual, please give feedback via our issue tracker (http://jadira.atlassian.net/) and GitHub (https://github.com/JadiraOrg/jadira/)  or through the mailing list.

 A big vote of thanks to all the users who have provided bug reports, and suggested fixes and new features during the preparation of the release.