Posts mit dem Label Spring werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Spring werden angezeigt. Alle Posts anzeigen

Montag, 2. April 2012

Extend existing EclipseLinkJpaVendorAdapter

The existing EclipseLinkJpaVendorAdapter allows you to set some basic functions. Most of the parameters are not configurable over the existing one. Here’s my extended version:
package de.mischur.utils;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;

public class ExtendedEclipseLinkJpaVendorAdapter extends EclipseLinkJpaVendorAdapter {

    public static final Logger log = LoggerFactory.getLogger(ExtendedEclipseLinkJpaVendorAdapter.class);

    private String targetServer = null;
    private String logger = null;
    private String profiler = null;

    private String cacheCoordinationNamingService = null;

    private String cacheCoordinationProtocol = null;

    private String jndiUser = null;

    private String jndiPwd = null;

    private String propagateAsynchronously = null;

    private String removeConnectionOnError = null;

    private String rmiUrl = null;

    private String rmiAnnouncementDelay = null;

    private String rmiMulticastGroup = null;

    private String rmiMulticastGroupPort = null;

    private String packetTime2Live = null;

    private String jmsTopic = null;

    private String jmsFactory = null;

    private String jmsHost = null;

    private String jmsReusePublisher = null;


    @Override
    public Map getJpaPropertyMap() {
        Map jpaProperties = super.getJpaPropertyMap();

        if (StringUtils.isNotEmpty(targetServer)) {
            jpaProperties.put(PersistenceUnitProperties.TARGET_SERVER, targetServer);
        }
        if (StringUtils.isNotEmpty(logger)) {
            jpaProperties.put(PersistenceUnitProperties.LOGGING_LOGGER, logger);
        }
        if (StringUtils.isNotEmpty(profiler)) {
            jpaProperties.put(PersistenceUnitProperties.PROFILER, profiler);
        }

        if (StringUtils.isNotEmpty(cacheCoordinationProtocol)) {
            jpaProperties.put(PersistenceUnitProperties.COORDINATION_PROTOCOL, cacheCoordinationProtocol);

            if (StringUtils.isNotEmpty(cacheCoordinationNamingService)) {
                jpaProperties.put(PersistenceUnitProperties.COORDINATION_NAMING_SERVICE, cacheCoordinationNamingService);
            }
            if (StringUtils.isNotEmpty(jndiUser)) {
                jpaProperties.put(PersistenceUnitProperties.COORDINATION_JNDI_USER, jndiUser);
            }

            if (StringUtils.isNotEmpty(jndiPwd)) {
                jpaProperties.put(PersistenceUnitProperties.COORDINATION_JNDI_PASSWORD, jndiPwd);
            }

            if (StringUtils.isNotEmpty(propagateAsynchronously)) {
                jpaProperties.put(PersistenceUnitProperties.COORDINATION_ASYNCH, propagateAsynchronously);
            }

            if (StringUtils.equalsIgnoreCase("rmi", cacheCoordinationProtocol)) {
                if (StringUtils.isNotEmpty(rmiUrl)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_RMI_URL, rmiUrl);
                }
                if (StringUtils.isNotEmpty(packetTime2Live)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_RMI_PACKET_TIME_TO_LIVE, packetTime2Live);
                }

                if (StringUtils.isNotEmpty(rmiMulticastGroup)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_RMI_MULTICAST_GROUP, rmiMulticastGroup);
                }

                if (StringUtils.isNotEmpty(rmiMulticastGroupPort)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_RMI_MULTICAST_GROUP_PORT, rmiMulticastGroupPort);
                }

                if (StringUtils.isNotEmpty(rmiAnnouncementDelay)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_RMI_ANNOUNCEMENT_DELAY, rmiAnnouncementDelay);
                }
                if (StringUtils.isNotEmpty(removeConnectionOnError)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_REMOVE_CONNECTION, removeConnectionOnError);
                }

            }
            if (StringUtils.equalsIgnoreCase("jms", cacheCoordinationProtocol)) {
                if (StringUtils.isNotEmpty(jmsTopic)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_JMS_TOPIC, jmsTopic);
                }
                if (StringUtils.isNotEmpty(jmsFactory)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_JMS_FACTORY, jmsFactory);
                }

                if (StringUtils.isNotEmpty(jmsHost)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_JMS_HOST, jmsHost);
                }
                if (StringUtils.isNotEmpty(jmsReusePublisher)) {
                    jpaProperties.put(PersistenceUnitProperties.COORDINATION_JMS_REUSE_PUBLISHER, jmsReusePublisher);
                }
            }
        }

 if (StringUtils.isNotEmpty(weavingInternal)) {
     jpaProperties.put(PersistenceUnitProperties.WEAVING_INTERNAL, Boolean.toString(BooleanUtils.toBoolean(weavingInternal)));
 }

        if (log.isDebugEnabled()) {
            log.debug("After setting own props");
            for (String key : jpaProperties.keySet()) {
                log.debug(key + "=" + jpaProperties.get(key));
            }
        }
        return jpaProperties;
    }

    public String getTargetServer() {
        return targetServer;
    }

    /**
     * Overrides the property <property>eclipselink.target-server</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#TARGET_SERVER
     */
    public void setTargetServer(String targetServer) {
        this.targetServer = targetServer;
    }

    public String getLogger() {
        return logger;
    }

    /**
     * Overrides the property <property>eclipselink.logging.logger</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#LOGGING_LOGGER
     */
    public void setLogger(String logger) {
        this.logger = logger;
    }

    public String getProfiler() {
        return profiler;
    }

    /**
     * Overrides the property <property>eclipselink.profiler</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#PROFILER
     */
    public void setProfiler(String profiler) {
        this.profiler = profiler;
    }

    public String getCacheCoordinationNamingService() {
        return cacheCoordinationNamingService;
    }

    public void setCacheCoordinationNamingService(String cacheCoordinationNamingService) {
        this.cacheCoordinationNamingService = cacheCoordinationNamingService;
    }

    public String getRemoveConnectionOnError() {
        return removeConnectionOnError;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.remove-connection-on-error</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_REMOVE_CONNECTION
     */
    public void setRemoveConnectionOnError(String removeConnectionOnError) {
        this.removeConnectionOnError = removeConnectionOnError;
    }

    public String getCacheCoordinationProtocol() {
        return cacheCoordinationProtocol;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.protocol</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_PROTOCOL
     */
    public void setCacheCoordinationProtocol(String cacheCoordinationProtocol) {
        this.cacheCoordinationProtocol = cacheCoordinationProtocol;
    }

    public String getRmiUrl() {
        return rmiUrl;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.rmi.url</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_RMI_URL
     */
    public void setRmiUrl(String rmiUrl) {
        this.rmiUrl = rmiUrl;
    }

    public String getJndiUser() {
        return jndiUser;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.jndi.user</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_JNDI_USER
     */
    public void setJndiUser(String jndiUser) {
        this.jndiUser = jndiUser;
    }

    public String getJndiPwd() {
        return jndiPwd;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.jndi.password</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_JNDI_PASSWORD
     */
    public void setJndiPwd(String jndiPwd) {
        this.jndiPwd = jndiPwd;
    }

    public String getPropagateAsynchronously() {
        return propagateAsynchronously;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.propagate-asynchronously</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_ASYNCH
     */
    public void setPropagateAsynchronously(String propagateAsynchronously) {
        this.propagateAsynchronously = propagateAsynchronously;
    }

    public String getRmiAnnouncementDelay() {
        return rmiAnnouncementDelay;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.rmi.announcement-delay</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_RMI_ANNOUNCEMENT_DELAY
     */
    public void setRmiAnnouncementDelay(String rmiAnnouncementDelay) {
        this.rmiAnnouncementDelay = rmiAnnouncementDelay;
    }

    public String getRmiMulticastGroup() {
        return rmiMulticastGroup;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.rmi.multicast-group</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_RMI_MULTICAST_GROUP
     */
    public void setRmiMulticastGroup(String rmiMulticastGroup) {
        this.rmiMulticastGroup = rmiMulticastGroup;
    }

    public String getRmiMulticastGroupPort() {
        return rmiMulticastGroupPort;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.rmi.multicast-group.port</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_RMI_MULTICAST_GROUP_PORT
     */
    public void setRmiMulticastGroupPort(String rmiMulticastGroupPort) {
        this.rmiMulticastGroupPort = rmiMulticastGroupPort;
    }

    public String getPacketTime2Live() {
        return packetTime2Live;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.rmi.packet-time-to-live</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_RMI_PACKET_TIME_TO_LIVE
     */
    public void setPacketTime2Live(String packetTime2Live) {
        this.packetTime2Live = packetTime2Live;
    }

    public String getJmsTopic() {
        return jmsTopic;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.jms.topic</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_JMS_TOPIC
     */
    public void setJmsTopic(String jmsTopic) {
        this.jmsTopic = jmsTopic;
    }

    public String getJmsFactory() {
        return jmsFactory;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.jms.factory</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_JMS_FACTORY
     */
    public void setJmsFactory(String jmsFactory) {
        this.jmsFactory = jmsFactory;
    }

    public String getJmsHost() {
        return jmsHost;
    }

    /**
     * Overrides the property <property>eclipselink.cache.coordination.jms.host</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_JMS_HOST
     */
    public void setJmsHost(String jmsHost) {
        this.jmsHost = jmsHost;
    }

    public String getJmsReusePublisher() {
        return jmsReusePublisher;
    }

    /**
     * Overrides the property <eclipselink.cache.coordination.jms.reuse-topic-publisher</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#COORDINATION_JMS_REUSE_PUBLISHER
     */
    public void setJmsReusePublisher(String jmsReusePublisher) {
        this.jmsReusePublisher = jmsReusePublisher;
    }

    public String getWeavingInternal() {
 return weavingInternal;
    }

    /**
     * Overrides the property <eclipselink.weaving.internal</property> from persistence.xml
     * @see org.eclipse.persistence.config.PersistenceUnitProperties#WEAVING_INTERNAL
     */
    public void setWeavingInternal(String weavingInternal) {
 this.weavingInternal = weavingInternal;
    }

}
And the related xml declaration:
  
    Config for EclipseLink
    
    
    
    
  

Montag, 18. April 2011

How to write a SqlTimestampPropertyEditor in Spring

Sometimes it is important to have your own PropertyEditor [see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/validation.html#beans-beans-conversion] in Spring, for example when you want to have SqlTimestamp as property in a bean. For this JavaType spring has no build-in PropertyEditor Implementation.

First step: Implement your SqlTimestampPropertyEditor:

package org.springframework.beans.propertyeditors;

import java.beans.PropertyEditorSupport;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
* Property editor for java.sql.Timestamp, supporting SimpleDateFormat.
*
* Using default Constructor uses the pattern yyyy-MM-dd
* Using the constructor with String, you can use your own pattern.
*
*/
public class SqlTimestampPropertyEditor extends PropertyEditorSupport {

public static final String DEFAULT_BATCH_PATTERN = "yyyy-MM-dd";

private final SimpleDateFormat sdf;

/**
* uses default pattern yyyy-MM-dd for date parsing.
*/
public SqlTimestampPropertyEditor() {
this.sdf = new SimpleDateFormat(SqlTimestampPropertyEditor.DEFAULT_BATCH_PATTERN);
}

/**
* Uses the given pattern for dateparsing, see {@link SimpleDateFormat} for allowed patterns.
*
* @param pattern
* the pattern describing the date and time format
* @see SimpleDateFormat#SimpleDateFormat(String)
*/
public SqlTimestampPropertyEditor(String pattern) {
this.sdf = new SimpleDateFormat(pattern);
}

/**
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
*/
@Override
public void setAsText(String text) throws IllegalArgumentException {

try {
setValue(new Timestamp(this.sdf.parse(text).getTime()));
} catch (ParseException ex) {
throw new IllegalArgumentException("Could not parse date: " + ex.getMessage(), ex);
}
}

/**
* Format the Timestamp as String, using the specified DateFormat.
*/
@Override
public String getAsText() {
Timestamp value = (Timestamp) getValue();
return (value != null ? this.sdf.format(value) : "");
}
}

Second Step: Register the SqlTimestampPropertyEditor
Open your application-context.xml file and define the bean:

<!-- A Custom Property Editor for SqlTimestamp -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.sql.Timestamp" value="org.springframework.beans.propertyeditors.SqlTimestampPropertyEditor">
</map>
</property>
</bean>

Third step: Use it in a different bean:

<bean id="exampleSimpleBean" class="org.springframework.example.SimpleBean">
<property name="timestamp">
<value type="java.sql.Timestamp">2008-01-01</value>
</property>
</bean>

<bean id="exampleMapBean" class="org.springframework.example.MapBean">
<property name="parameterValues">
<map>
<entry key="timestamp">
<value type="java.sql.Timestamp">2008-01-01</value>
</entry>
</map>
</property>
</bean>

Where the date (2008-01-31) is defined you can also use the spring expression language to access application wide or scope wide variables.

Bean class examples:

org.springframework.example.SimpleBean

package org.springframework.example;

import java.sql.Timestamp;

public class SimpleBean {

private Timestamp timestamp;

public Timestamp getTimestamp() {
return timestamp;
}

public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
}

org.springframework.example.MapBean

package org.springframework.example;

import java.util.Map;

public class MapBean {

private Map parameterValues;

public void setParameterValues(Map parameterValues) {
this.parameterValues = parameterValues;
}
}

In another article we will see why I need a special SqlTimestampPropertyEditor

Freitag, 25. März 2011

Set custom connection property to Apache Commons DBCP BasicDataSource via Spring config

When you want to set a custom connection Property to the BasicDataSource from Apache commons dbcp you need to use the method: public void addConnectionProperty(String name, String value)

You can't use the normal spring config to add a property because the variable connectionProperties has no getter and setter method.

Here's the example:
Spring context.xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="connectionProperties">
<props>
<prop key="includeSynonyms">true</prop>
</props>
</property>
</bean>

In your code you try to autowire the datasource like this:

@Autowired
protected javax.sql.DataSource dataSource;


If you try this, you will get the following exception:
org.springframework.beans.NotWritablePropertyException: Invalid property 'connectionProperties' of bean class [org.apache.commons.dbcp.BasicDataSource]: Bean property 'connectionProperties' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?

How can you solve this problem?
Using the addConnectionProperty Method from BasicDataSource? Yes. But you can't access it at the moment directly in the spring config.
There is a ImprovementRequest for Spring and the planed to solve it in Spring Core Release 3.2RC1.


The other way would be:
Create your own Interface which extends javax.sql.DataSource
and extends the org.apache.commons.dbcp.BasicDataSource class with your own implementation

ExtendDataSource interface

package com.apache.dbutils;

import javax.sql.DataSource;

public interface ExtendDataSource extends DataSource {

public String getIncludeSynonyms();

public void setIncludeSynonyms(String includeSynonyms);
}


ExtendBasicDataSource Class

package com.apache.dbutils;

import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.dbutils.ExtendDataSource;

public class ExtendBasicDataSource extends BasicDataSource
implements ExtendDataSource {

public ExtendBasicDataSource () {
super();
}

/**
* @see java.sql.Wrapper#unwrap(java.lang.Class)
*/
@Override
public T unwrap(Class iface) {
throw new UnsupportedOperationException("Is not implemented by org.apache.commons.dbcp.BasicDataSource so we will not implement it either");
}

/**
* @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
*/
@Override
public boolean isWrapperFor(Class iface) throws SQLException {
throw new UnsupportedOperationException("Is not implemented by org.apache.commons.dbcp.BasicDataSource so we will not implement it either");
}

/**
* @see com.wirecard.settlement.dbutils.SettlementDataSource#getIncludeSynonyms()
*/
@Override
public String getIncludeSynonyms() {
return super.connectionProperties.getProperty("includeSynonyms");
}

/**
* @see com.wirecard.settlement.dbutils.SettlementDataSource#setIncludeSynonyms(java.lang.String)
*/
@Override
public void setIncludeSynonyms(String includeSynonyms) {
super.addConnectionProperty("includeSynonyms", String.valueOf(includeSynonyms));
}
}


And now you need to change your Spring Config

<bean id="dataSource" class="com.apache.dbutils.ExtendBasicDataSource" method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="includeSynonyms" value="true" />
</bean>


You don't need to change your code where you autowire the datasource.