MS CRM Not Saving Some Attributes When Entity First Created - dynamics-crm-4

I've got a custom entity in MS Dynamics CRM 4 (old, yes I know, we're planning on migrating to newer soon). I've got the "main application form" showing some of the custom attributes that are on the entity. When a new record is created for this entity there are some attributes that don't get saved (some lookups to related entities, and a decimal field attribute). These attributes are not read-only, there is no client-side scripting, and no workflows to prevent saving the attributes. The user I'm testing with has full "System Administrator" permission with access to all custom entities, so it shouldn't be a permission issue. I've turned on verbose trace logging for CRM, and it appears that the CRM engine is being told to save the attributes:
>InProcessCrmService starts processing request for user:CreateRequest
As user:xxxxxxxx-e990-dd11-870d-005056c00008
Request Xml:
<?xml version="1.0" encoding="utf-16"?>
<CreateRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/crm/2007/WebServices">
<OptionalParameters>
<OptionalParameter xsi:type="CreateDuplicatesOptionalParameter">
<Value>false</Value>
</OptionalParameter>
</OptionalParameters>
<Target xsi:type="TargetCreateDynamic">
<Entity Name="new_job">
<Properties xmlns="http://schemas.microsoft.com/crm/2006/WebServices">
<Property xsi:type="OwnerProperty" Name="ownerid">
<Value name="Joe Blow Admin" type="systemuser">xxxxxxxx-aa8f-e111-8548-005056c00008</Value>
</Property>
<Property xsi:type="LookupProperty" Name="new_accountid">
<Value name="A Walk In Client" type="account">xxxxxxx-22cd-dd11-9db5-005056c00008</Value>
</Property>
<Property xsi:type="PicklistProperty" Name="new_childcompany">
<Value name="Road Pavers Inc">4</Value>
</Property>
<Property xsi:type="CrmDateTimeProperty" Name="new_startdate">
<Value>2016-06-12T00:00:00</Value>
</Property>
<Property xsi:type="CrmDateTimeProperty" Name="new_enddate">
<Value>2016-06-15T00:00:00</Value>
</Property>
<Property xsi:type="CrmBooleanProperty" Name="new_productionjob">
<Value>false</Value>
</Property>
<Property xsi:type="CrmBooleanProperty" Name="new_billed">
<Value>false</Value>
</Property>
<Property xsi:type="LookupProperty" Name="new_revenuecityid">
<Value name="Toronto" type="new_citylocation">xxxxxxxx-6eda-e511-aa42-0050569e01ef</Value>
</Property>
<Property xsi:type="LookupProperty" Name="new_industrycodeid">
<Value name="Other" type="new_industrycode">xxxxxxxx-6eda-e511-aa42-0050569e01ef</Value>
</Property>
<Property xsi:type="LookupProperty" Name="new_jobconfidencelevelid">
<Value name="Low" type="new_jobconfidence">xxxxxxxx-1124-e611-aa44-0050569e01ef</Value>
</Property>
<Property xsi:type="CrmDecimalProperty" Name="new_estimatedhoursperday">
<Value>5.3</Value>
</Property>
<Property xsi:type="StringProperty" Name="new_description">
<Value>Testing job creation</Value>
</Property>
<Property xsi:type="PicklistProperty" Name="new_avgweight">
<Value name="Heavy">1</Value>
</Property>
<Property xsi:type="LookupProperty" Name="transactioncurrencyid">
<Value name="Canadian Dollar" type="transactioncurrency">a0599012-25f2-dc11-9dc3-00c09f3657d9</Value>
</Property>
<Property xsi:type="StateProperty" Name="statecode">
<Value>Active</Value>
</Property>
</Properties>
</Entity>
</Target>
</CreateRequest>
I've also used SQL server profiling to see what actually gets sent to SQL:
exec sp_executesql
N'insert into New_JobBase(
ExchangeRate,
OwningBusinessUnit,
New_JobId,
CreatedOn,
StateCode,
StatusCode,
OwningUser,
ModifiedBy,
CreatedBy,
DeletionStateCode,
ModifiedOn,
TransactionCurrencyId)
values (
#ExchangeRate0,
#OwningBusinessUnit0,
#New_JobId0,
#CreatedOn0,
#StateCode0,
#StatusCode0,
#OwningUser0,
#ModifiedBy0,
#CreatedBy0,
#DeletionStateCode0,
#ModifiedOn0,
#TransactionCurrencyId0);
insert into New_JobExtensionBase(
new_accountid,
New_EndDate,
New_JobId,
New_Description,
New_ChildCompany,
New_Billed,
New_StartDate,
New_avgweight,
New_ProductionJob)
values (
#new_accountid0,
#New_EndDate0,
#New_JobId1,
#New_Description0,
#New_ChildCompany0,
#New_Billed0,
#New_StartDate0,
#New_avgweight0,
#New_ProductionJob0)',
N'#ExchangeRate0 decimal(11,10),
#OwningBusinessUnit0 uniqueidentifier,
#New_JobId0 uniqueidentifier,
#CreatedOn0 datetime,
#StateCode0 int,
#StatusCode0 int,
#OwningUser0 uniqueidentifier,
#ModifiedBy0 uniqueidentifier,
#CreatedBy0 uniqueidentifier,
#DeletionStateCode0 int,
#ModifiedOn0 datetime,
#TransactionCurrencyId0 uniqueidentifier,
#new_accountid0 uniqueidentifier,
#New_EndDate0 datetime,
#New_JobId1 uniqueidentifier,
#New_Description0 ntext,
#New_ChildCompany0 int,
#New_Billed0 bit,
#New_StartDate0 datetime,
#New_avgweight0 int,
#New_ProductionJob0 bit
',
#ExchangeRate0=1.0000000000,
#OwningBusinessUnit0='xxxxxxxx-E990-DD11-870D-005056C00008',
#New_JobId0='xxxxxxxx-0838-E611-AA44-0050569E01EF',
#CreatedOn0='Jun 21 2016 11:35:22:000PM',
#StateCode0=0,
#StatusCode0=1,
#OwningUser0='xxxxxxxx-AA8F-E111-8548-005056C00008',
#ModifiedBy0='xxxxxxxx-AA8F-E111-8548-005056C00008',
#CreatedBy0='xxxxxxxx-AA8F-E111-8548-005056C00008',
#DeletionStateCode0=0,
#ModifiedOn0='Jun 21 2016 11:35:22:000PM',
#TransactionCurrencyId0='A0599012-25F2-DC11-9DC3-00C09F3657D9',
#new_accountid0='xxxxxxxx-22CD-DD11-9DB5-005056C00008',
#New_EndDate0='Jun 15 2016 6:00:00:000AM',
#New_JobId1='xxxxxxxx-0838-E611-AA44-0050569E01EF',
#New_Description0=N'Testing job creation',
#New_ChildCompany0=4,
#New_Billed0=0,
#New_StartDate0='Jun 12 2016 6:00:00:000AM',
#New_avgweight0=1,
#New_ProductionJob0=0
As you can see above, some attributes, like new_avgweight, new_description, or a lookup like the new_accountid are being created properly. Other attributes, like new_industrycode or new_estimatedhoursperday are not being passed along to SQL.
Once the record has been created, it is possible to open it up, enter the data and it will save correctly. It is only failing to save when it is a new record first being created.
Why does it seem like CRM is saving some atttributes, but not other attributes? I've tried deleting an attribute and adding it back to the entity to see if that would force CRM to re-generate it, but to no avail.

Related

Print XML attribute in SQL Server

I am trying to get value of an attribute from XML in SQL table
<?xml version="1.0" encoding="utf-8"?>
<container>
<Property Name="paramA" Vocabulary="someVocu">
<Property Name="paramB" Value="valueA" />
<Property Name="paramC" Value="valueB" />
</Property>
<Property Name="paramA" Vocabulary="anotherVocu">
<Property Name="paramB" Value="valueY" />
<Property Name="paramC" Value="valueZ" />
</Property>
</container>
select x.XmlCol.value('(Property[#Name="paramB"]/#Value)[1]', 'varchar(50)') from tempTbl CROSS APPLY rawxml.nodes('/container') AS x(XmlCol)
I am trying to print "valueA" and "valueY" I am getting a NULL.
How can I do this?
Thanks
I cannot tell you what in particular is wrong with your statement since I am still learning how to query XML too. I was able to come up with some SQL which I think should work for by referencing this question...
How to query for Xml values and attributes from table in SQL Server?
Here it is.
CREATE TABLE tempTbl
(
id INT,
data XML
)
INSERT INTO dbo.tempTbl
(id, data)
SELECT 1, '<?xml version="1.0" encoding="utf-8"?>
<container>
<Property Name="paramA" Vocabulary="someVocu">
<Property Name="paramB" Value="valueA" />
<Property Name="paramC" Value="valueB" />
</Property>
<Property Name="paramA" Vocabulary="anotherVocu">
<Property Name="paramB" Value="valueY" />
<Property Name="paramC" Value="valueZ" />
</Property>
</container>'
SELECT
x.XmlCol.value('#Value', 'varchar(25)') AS Value
FROM tempTbl AS t
CROSS APPLY t.data.nodes('/container/Property/Property') AS x(XmlCol)
WHERE x.XmlCol.value('#Name', 'varchar(25)') = 'paramB'
To learn more about querying XML I am working through Stairway to XML.
Noel

Duplicate record errors in Hibernate Search backed by Infinispan in an EC2 cluster

We have an application that works in an EC2 cluster (2 nodes currently for testing). For searching domain models we use Hibernate Search, and since the application runs on a cluster we use Infinispan as the Lucene Directory. To survive restarts we use a JDBC cache store on MySQL, both nodes accessing the same MySQL tables. To account for adding and removing nodes, we use the "jgroups" backend for Hibernate Search worker configuration.
Our problem is about duplicate records exceptions we receive when we try to rebuild the whole entity index. We get errors with similar stacktraces as this:
ERROR [AsyncStoreProcessor-LuceneIndexesData-0] [2016-06-21 17:01:59] org.infinispan.persistence.jdbc.stringbased.JdbcStringBasedStore - ISPN008024: Error while storing string key to database; key: '_d.fdt|0|1048576|com.model.SomeModel'
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '_d.fdt|0|1048576|com.model.SomeModel' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1041)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4190)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4122)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1399)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:857)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2460)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2377)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2361)
at com.zaxxer.hikari.proxy.PreparedStatementJavassistProxy.executeUpdate(PreparedStatementJavassistProxy.java)
at org.infinispan.persistence.jdbc.stringbased.JdbcStringBasedStore.write(JdbcStringBasedStore.java:174)
at org.infinispan.persistence.async.AsyncCacheWriter.applyModificationsSync(AsyncCacheWriter.java:158)
at org.infinispan.persistence.async.AsyncCacheWriter$AsyncStoreProcessor.retryWork(AsyncCacheWriter.java:330)
at org.infinispan.persistence.async.AsyncCacheWriter$AsyncStoreProcessor.run(AsyncCacheWriter.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
When we check the DB, there is an entry with this ID. When we try it with a single node there are no errors. So our guess is both nodes are trying to write the cache entry to DB. What may be causing this problem? AFAIK the jgroups backend should be preventing it.
We use hibernate 4.3.9.Final, hibernate-search 5.2.1.Final, infinispan 7.2.5.Final and jgroups 3.6.8.Final. Infinispan configuration is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<infinispan xmlns="urn:infinispan:config:7.2"
xmlns:jdbc="urn:infinispan:config:store:jdbc:7.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
urn:infinispan:config:7.2 http://www.infinispan.org/schemas/infinispan-config-7.2.xsd
urn:infinispan:config:store:jdbc:7.2 http://www.infinispan.org/schemas/infinispan-cachestore-jdbc-config-7.2.xsd">
<jgroups>
<stack-file name="tcp" path="default-configs/default-jgroups-tcp.xml"/>
<stack-file name="ec2" path="search/infinispan-jgroups-ec2.xml"/>
</jgroups>
<cache-container name="HibernateSearch" default-cache="default" statistics="false" shutdown-hook="DONT_REGISTER">
<transport stack="${infinispan.transport:tcp}"/>
<!-- Duplicate domains are allowed so that multiple deployments with default configuration
of Hibernate Search applications work - if possible it would be better to use JNDI to share
the CacheManager across applications -->
<jmx duplicate-domains="true"/>
<!-- *************************************** -->
<!-- Cache to store Lucene's file metadata -->
<!-- *************************************** -->
<replicated-cache name="LuceneIndexesMetadata" mode="SYNC" remote-timeout="25000">
<transaction mode="NONE"/>
<state-transfer enabled="true" timeout="480000" await-initial-transfer="true"/>
<indexing index="NONE"/>
<locking striping="false" acquire-timeout="10000" concurrency-level="500" write-skew="false"/>
<eviction max-entries="-1" strategy="NONE"/>
<expiration max-idle="-1"/>
<persistence passivation="false">
<jdbc:string-keyed-jdbc-store preload="true" fetch-state="true" read-only="false" purge="false">
<jdbc:data-source jndi-url="java:comp/env/jdbc/..."/>
<jdbc:string-keyed-table drop-on-exit="false" create-on-start="true" prefix="ISPN_STRING_TABLE">
<jdbc:id-column name="ID" type="VARCHAR(255)"/>
<jdbc:data-column name="METADATA" type="BLOB"/>
<jdbc:timestamp-column name="TIMESTAMP" type="BIGINT"/>
</jdbc:string-keyed-table>
<property name="key2StringMapper">org.infinispan.lucene.LuceneKey2StringMapper</property>
<write-behind/>
</jdbc:string-keyed-jdbc-store>
</persistence>
</replicated-cache>
<!-- **************************** -->
<!-- Cache to store Lucene data -->
<!-- **************************** -->
<distributed-cache name="LuceneIndexesData" mode="SYNC" remote-timeout="25000">
<transaction mode="NONE"/>
<state-transfer enabled="true" timeout="480000" await-initial-transfer="true"/>
<indexing index="NONE"/>
<locking striping="false" acquire-timeout="10000" concurrency-level="500" write-skew="false"/>
<eviction max-entries="-1" strategy="NONE"/>
<expiration max-idle="-1"/>
<persistence passivation="false">
<jdbc:string-keyed-jdbc-store preload="true" fetch-state="true" read-only="false" purge="false">
<jdbc:data-source jndi-url="java:comp/env/jdbc/..."/>
<jdbc:string-keyed-table drop-on-exit="false" create-on-start="true" prefix="ISPN_STRING_TABLE">
<jdbc:id-column name="ID" type="VARCHAR(255)"/>
<jdbc:data-column name="DATA" type="MEDIUMBLOB"/>
<jdbc:timestamp-column name="TIMESTAMP" type="BIGINT"/>
</jdbc:string-keyed-table>
<property name="key2StringMapper">org.infinispan.lucene.LuceneKey2StringMapper</property>
<write-behind/>
</jdbc:string-keyed-jdbc-store>
</persistence>
</distributed-cache>
<!-- ***************************** -->
<!-- Cache to store Lucene locks -->
<!-- ***************************** -->
<replicated-cache name="LuceneIndexesLocking" mode="SYNC" remote-timeout="25000">
<transaction mode="NONE"/>
<state-transfer enabled="true" timeout="480000" await-initial-transfer="true"/>
<indexing index="NONE"/>
<locking striping="false" acquire-timeout="10000" concurrency-level="500" write-skew="false"/>
<eviction max-entries="-1" strategy="NONE"/>
<expiration max-idle="-1"/>
</replicated-cache>
</cache-container>
</infinispan>
Respective Hibernate configuration is as follows (which is done via Spring):
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="..."/>
<property name="packagesToScan" value="com...."/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false"/>
<property name="showSql" value="false"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="database" value="MYSQL"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.default_batch_fetch_size" value="50"/>
<entry key="hibernate.multiTenancy" value="SCHEMA"/>
<entry key="hibernate.multi_tenant_connection_provider" value-ref="connectionProvider"/>
<entry key="hibernate.tenant_identifier_resolver" value-ref="tenantIdentifierResolver"/>
<entry key="hibernate.cache.use_second_level_cache" value="true"/>
<entry key="hibernate.cache.region.factory_class" value="com.hazelcast.hibernate.HazelcastCacheRegionFactory"/>
<entry key="hibernate.cache.hazelcast.use_native_client" value="true"/>
<entry key="hibernate.cache.hazelcast.native_client_address" value="127.0.0.1"/>
<entry key="hibernate.cache.hazelcast.native_client_group" value="dev"/>
<entry key="hibernate.cache.hazelcast.native_client_password" value="dev-pass"/>
<entry key="hibernate.connection.characterEncoding" value="UTF-8"/>
<entry key="hibernate.connection.useUnicode" value="true"/>
<entry key="hibernate.search.default.directory_provider" value="infinispan"/>
<entry key="hibernate.search.default.locking_cachename" value="LuceneIndexesLocking"/>
<entry key="hibernate.search.default.data_cachename" value="LuceneIndexesData"/>
<entry key="hibernate.search.default.metadata_cachename" value="LuceneIndexesMetadata"/>
<entry key="hibernate.search.default.chunk_size" value="1048576"/>
<entry key="hibernate.search.infinispan.configuration_resourcename" value="search/hibernatesearch-infinispan.xml"/>
<entry key="hibernate.search.default.worker.backend" value="jgroups"/>
<entry key="hibernate.search.services.jgroups.configurationFile" value="search/infinispan-jgroups-ec2.xml"/>
</map>
</property>
</bean>
You are correct on the purpose of the JGroups Backend and your configuration of Hibernate looks like correct.
The problem is on the configuration of the CacheStore component in Infinispan, these have a "shared" attribute, whose default is false.
<jdbc:string-keyed-jdbc-store
preload="true"
fetch-state="true"
read-only="false"
purge="false"
shared="true" <!-- FIX
As you suspected, each Infinispan node was going to re-write the same entry on "each" CacheStore instance, as it didn't guess that each of your nodes are actually connecting to the same database.
Setting the shared attribute to true should ensure that Infinispan's core will coordinate among nodes so that one (and only one) node will write the entry.

How to set up deployerConfigContext.xml to add attributes to cas?

I used CAS server 4.0 and cas-overlay-server-demo. the return value of my server is as following:
<cas:serviceResponse xmlns:cas="xxx">
<cas:authenticationSuccess>
<cas:user>try</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
I want to add <cas:attributes> to this return result. I have following code in deployerConfigContext.xml:
primaryAuthenticationHandler:
<bean id="primaryAuthenticationHandler" class="org.jasig.cas.authentication.AcceptUsersAuthenticationHandler">
<property name="users">
<map>
<entry key="test" value="1234"/>
</map>
</property>
</bean>
primaryPrincipalResolver:
<bean id="primaryPrincipalResolver"
class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
<property name="attributeRepository" ref="attributeRepository" />
</bean>
attributeRepository:
<bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
p:backingMap-ref="attrRepoBackingMap" />
<util:map id="attrRepoBackingMap">
<entry key="uid" value="uid" />
<entry key="prénom" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
</util:map>
I think I have add the the code right. StubPersonAttributeDao will help me to add attributes: uid and prénom and groupMembership. BUT, I still do not get any attibutes. Is there anything wrong in the code?
You probably need to authorize your application in CAS service registry to release attributes. By default, nothing is allowed. See http://apereo.github.io/cas/4.0.x/integration/Attribute-Release.html

spring + hibernate integration Table "table_name " is missing

I'm integrate spring with hibernate , I'm using dropwizard configaration files as : persistence file have the configuration files are in resources folder no issue with loading xml files. There is issue with found table .
persistence.xml file as :
<persistence-unit name="bfm" transaction-type="RESOURCE_LOCAL" >
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.bcits.parkingmanagement.model.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<!-- Configuring JDBC properties -->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/anuj" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
</persistence-unit>
</persistence>
In spring application config xml as : there I show only hibernate configuration
<context:annotation-config />
<context:component-scan base-package="com.bcits.parkingmanagement.model" />
<jdbc:embedded-database id="dataSource" type="HSQL" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:spring/persistence.xml" />
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManager"
class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Table User missing
javax.persistence.PersistenceException: [PersistenceUnit: bfm] Unable to build EntityManagerFactory
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
... 18 more
Caused by: org.hibernate.HibernateException: Missing table: user
Please anyone help me how can I resolve this error. I want to configuration of spring with hibernate.I thing it is connect to database but can't found table. Table name and colume name exactly same. Database name also correct and no issue with username and password of database .
User model is: Here User is model name and user is table which have two column one is user_id and user_name. Issue is that i had used user instead of User in query. Because User is model name and user is table name .Correct model is given below
#NamedQueries({
#NamedQuery( name="getUserName" , query="select name from User")
})
#Entity
#Table( name ="user")
public class User {
#Id
#Column( name="user_id")
private int id;
#Column( name="user_name")
private String name;
//getter setter
}

Why are transactions not rolling back when using SpringJUnit4ClassRunner/MySQL/Spring/Hibernate

I am doing unit testing and I expect that all data committed to the MySQL database will be rolled back... but this isn't the case. The data is being committed, even though my log was showing that the rollback was happening. I've been wrestling with this for a couple days so my setup has changed quite a bit, here's my current setup.
LoginDAOTest.java:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"file:web/WEB-INF/applicationContext-test.xml", "file:web/WEB-INF/dispatcher-servlet-test.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class UserServiceTest {
private UserService userService;
#Test
public void should_return_true_when_user_is_logged_in ()
throws Exception
{
String[] usernames = {"a","b","c","d"};
for (String username : usernames)
{
userService.logUserIn(username);
assertThat(userService.isUserLoggedIn(username), is(equalTo(true)));
}
}
ApplicationContext-Text.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/******"/>
<property name="username" value="*****"/>
<property name="password" value="*****"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="userService" class="Service.UserService">
<property name="userDAO" ref="userDAO"/>
</bean>
<bean id="userDAO" class="DAO.UserDAO">
<property name="hibernateTemplate" ref="hibernateTemplate"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>/himapping/User.hbm.xml</value>
<value>/himapping/setup.hbm.xml</value>
<value>/himapping/UserHistory.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</beans>
I have been reading about the issue, and I've already checked to ensure that the MySQL database tables are setup to use InnoDB. Also I have been able to successfully implement rolling back of transactions outside of my testing suite. So this must be some sort of incorrect setup on my part.
Any help would be greatly appreciated :)
The problem turned out to be that the connection was auto-committing BEFORE the transaction could be rolled back. I had to change my dataSource bean to include a defaultAutoCommit property:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="Ecosim07"/>
<property name="defaultAutoCommit" value="false" />
</bean>
For me defaultAutoCommit and #Transactional didn't help. I had to change db type to InnoDB
Another way to fix your problem:
Instead of using:
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
, which creates a MyISAM table by default, hence not supporting transactions
Try using
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
, which creates InnoDB tables, and thus supports transactions.
This must be used
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
#TestExecutionListeners({ TransactionalTestExecutionListener.class })
#Transactional
TransactionalTestExecutionListener contains isRollback() which rollbacks the
transaction after the test method.
I hope I am right and that this is a simple one. You are missing the #Transactional annotation on your test class. This means that the test method itself isn't run in a transaction and thus there is nothing to roll back. Hope this helps.