Spring data #transactional not rolling back with SQL Server and after runtimeexception - sql-server

I've enabled my spring application to use transactions and annotated my service method accordingly but the changes to my DB persist when a RuntimeException is thrown.
My Spring configuration looks like this:
<!-- Data Source. -->
<jee:jndi-lookup id="dataSource" jndi-name="java:/jdbc/BeheermoduleDS"/>
<!-- JPA Entity Manager. -->
<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/jpa/BeheermoduleDS"/>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
My datasource configuration in my jboss' configuration file looks like this:
<datasource jta="true" jndi-name="java:/jdbc/BeheermoduleDS" pool-name="BeheermoduleDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:sqlserver://localhost:1433;databaseName=Gebruikers;</connection-url>
<driver>sqljdbc</driver>
<security>
<user-name>jboss</user-name>
<password>*****</password>
</security>
</datasource>
My Service method looks like this:
#Transactional
public void authorise(Gebruiker user) {
user.setStatus(GebruikerStatus.Actief.name());
gebruikerRepo.save(user);
if (true) {
throw new RuntimeException("Exception happened just like that");
}
// does more stuff here that is never reached
}
My repository extends a spring data repository and looks like this:
public interface GebruikerRepository extends PagingAndSortingRepository<Gebruiker, Long>, QueryDslPredicateExecutor<Gebruiker> {
}
The transaction is thrown and caught by a controller which just shows a message to the user that an exception occurred. When I check my SQL Server DB, the change made to the user status have been commited.
Weren't they supposed to have been rolled back with the RuntimeException?
After turning debug on for org.springframework.transaction.interceptor I saw that no transactions are being started for my service method, but they are for a bunch of JpaRepository methods.
Also, this is how my persistence.xml looks like:
<persistence-unit name="BeheermodulePU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>java:/jdbc/BeheermoduleDS</non-jta-data-source>

Judging from the symptoms you describe you are scanning for the same classes twice. You probably have the same <context:component-scan /> in both the configuration of the ContextLoaderListener and DispatcherServlet.
You want the ContextLoaderListener to scan for everything but #Controller and the DispatcherServlet only for #Controllers. Leading to something like this.
For the ContextLoaderListener
<!-- Load everything except #Controllers -->
<context:component-scan base-package="com.myapp">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
For the DispatcherServlet
<!-- Load everything except #Controllers -->
<context:component-scan base-package="com.myapp" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
See also #Service are constructed twice for another sample and broader explanation.

Related

How to fix inconsistency in Jackrabbit JCR (BundleFsPersistenceManager)

We are using JackRabbit in production. Unfortunately we have some inconsistencies in the repositories which make the data not unreadable:
ERROR ResourceServiceImpl - RepositoryException to JCR javax.jcr.PathNotFoundException: 1661b5c
The spring bean configuration looks like this:
<bean id="repository" class="org.apache.jackrabbit.core.RepositoryImpl" destroy-method="shutdown">
<constructor-arg index="0" ref="config" />
</bean>
<bean id="config" class="org.apache.jackrabbit.core.config.RepositoryConfig" factory-method="create">
<constructor-arg index="0" ref="jcrXml"/>
<constructor-arg index="1" value="${instance.repository}" />
</bean>
<bean id="jcrXml" class="com.example.misc.InputStreamBeanFactory" factory-method="createStream">
<constructor-arg value="/jackrabbit-repository.xml" />
</bean>
<bean name="jcrSession" factory-bean="repository" factory-method="login" scope="session" destroy-method="logout" />
The workspaces.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?><Workspace name="default">
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${wsp.home}"/>
</FileSystem>
<PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager"/>
</Workspace>
From what I've learned (too late) here, the above configured BundleFsPersistenceManager can become inconsistent. It is also writen here that this should NOT be used into production. Well, it is now in production and no one has noticed this before and we would like to exchange this. However first we have to migrate the data and for this reason we need to fix it.
My question: Is there a way to fix this or are these data lost for good?
My second question: What can we do to avoid these issues in the future?.
There's some notes about additional check.. params that can be set on persistence managers on Adobe CQ - Repository Inconsistency (uses Jackrabbit). The Magnolia - JCR Troubles has a script example for searching for and removing broken nodes. I've seen an approach that combined the logic from this script (written in java) and the checking params allow for a repository to be brought back up and running long enough to get the content out.
To avoid the issues in future - where you want a standalone setup that doesn't use a RDBMS - I'd suggest org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager.
<PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager">
<param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
<param name="schemaObjectPrefix" value="${wsp.name}_"/>
</PersistenceManager>

cxf-rs-ws authorization under karaf

I'm trying to configure a cxf soap webservice with authorization and authentication to be deployed on Servicemix.
I configured the LDAP authentication module as follows:
<!-- Bean to allow the $[karaf.base] property to be correctly resolved -->
<ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
<jaas:config name="myRealm">
<jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="required">
connection.url = ldap://srv-ldap:389
user.base.dn = ou=people,dc=intranet,dc=company,dc=com
user.filter = (uid=%u)
user.search.subtree = false
role.base.dn = ou=groups,dc=intranet,dc=company,dc=com
role.filter = (member:=uid=%u,ou=people,dc=intranet,dc=company,dc=com)
role.name.attribute = cn
role.search.subtree = true
authentication = simple
</jaas:module>
</jaas:config>
<service interface="org.apache.karaf.jaas.modules.BackingEngineFactory">
<bean class="org.apache.karaf.jaas.modules.properties.PropertiesBackingEngineFactory"/>
</service>
And here is the beans.xml file
<jaxws:endpoint id="myService"
implementor="com.myorg.services.impl.MyServiceWSImpl"
address="/myService">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
</map>
</constructor-arg>
</bean>
<ref bean="authenticationInterceptor" />
<ref bean="authorizationInterceptor" />
</jaxws:inInterceptors>
<jaxws:properties>
<entry key="ws-security.validate.token" value="false" />
</jaxws:properties>
</jaxws:endpoint>
<bean id="authenticationInterceptor"
class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
<property name="contextName" value="myRealm" />
</bean>
<bean id="authorizationInterceptor"
class="org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor">
<property name="securedObject" ref="securedBean"/>
</bean>
Finally, in my WebService implementation I annotated a method with #RolesAllowed.
#RolesAllowed("Role1")
public Department get(String name) throws IdMException {
return service.get(name);
}
The authentication interceptor is retrieving the user, authenticating it and retrieving the groups as RolePrincipal instances.
Then, in the authorization interceptor (SecureAnnotationsInterceptor), the method configuration is read, the expectedRoles are "Role1", but the SimpleAuthorizingInterceptor.isUserInRole method returns false.
I haven't found any example trying to do more or less the same and the few information I found was from the CXF documentation page http://cxf.apache.org/docs/security.html#Security-Authorization
I have to be missing something important, hope somebody could help me.
Thanks in advance and kind regards.
Your problem is because of Karaf's RolePricipal do not implements Group as CXF expected. Instead of it, it implements Pricipal so CXF thinks that 1st role name is a username. That is why "SimpleAuthorizingInterceptor.isUserInRole method returns false".
A solution is to wait for fixed versions of CXF (2.7.11 and 3.0.0).
If not possible to update to newer version, then an odd and temporary solution (simply workaround) is to add more than one role to a user in LDAP and to method.
You can find more about that bug here: CXF-5603

How to view the inserted rows when JPA testing with arquillian / hibernate?

I have an arquillian unit test that is writing a Note and passing the unit tests.
Now I would like to actually view what is being persisted into my SQLServer database.
When I open up SQLServer, I see my "Note" table, with all of the requisite columns...but there's no data.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="noteUnit"
transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/jdbc/datasources/notes</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2005Dialect" />
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence>
I've tried various values for hbm22ddl.auto--'create-drop', 'update','validate', but since my test passes, I assume that the new rows are being inserted and then immediately removed by arquillian after the unit test?
Unit test below passes--meaning arquillian's xml file and all the other assorted plumbing appears to be set up correctly. Is there a setting somewhere to save all the data that's being inserted?
private NoteEntity createNote(){
NoteEntity note = new NoteEntity();
note.setGuid("123456789");
note.setAuthorId("12345");
return note;
}
#Test
public void createNoteTest(){
NoteEntity note1 = createNote();
mEntityManager.persist(note1);
Assert.assertNotNull(note1.getId());
}
Generally, jUnit are configured so that their transaction is in defaultrollback=true mode. This is done to avoid inserting test data in your database. You will probably find the configuration over your class definition or in an extended class.
Example for jUnit with Spring IOC configuration :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath*:myPath/spring*Context.xml")
#TransactionConfiguration(defaultRollback = true)
#Transactional
public abstract class AbstactSpringTestCase {
...
}

JPA does not write to table

I have the following JPA code, with all the values checked (ticket contains a valid bean, it ends without exception, etc.) It is executed, it does not throw any exceptions, yet in the end no data is written into the table.
I tried also retrieving a bean from the table, it also "works" (it is empty, so no data is returned).
The setup is
JBoss 6.1 Final
SQLServer 2008 Express (driver SQL JDBC 3 from MS)
The persistence code:
public String saveTicket() {
System.out.println("Controller saveTicket() ");
EntityManagerFactory factory = Persistence.createEntityManagerFactory("GesMan"); /* I know it would be better to share a single instance of factory, this is just for testing */
EntityManager entityMan = factory.createEntityManager();
entityMan.persist(this.ticket);
entityMan.close();
}
The persistence unit is
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="GesMan" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/GesManDS</jta-data-source>
<class>es.caib.gesma.gesman.Ticket</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
The datasource
<datasources>
<local-tx-datasource>
<jndi-name>GesManDS</jndi-name>
<connection-url>jdbc:sqlserver://spsigeswnt14.caib.es:1433;DatabaseName=TEST_GESMAN</connection-url>
<driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
<user-name>thisis</user-name>
<password>notthepassword</password>
<check-valid-connection-sql>SELECT * FROM dbo.Ticket</check-valid-connection-sql>
<metadata>
<type-mapping>MS SQLSERVER</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
call entityMan.flush() or transaction.commit() befor closing it, otherwise it will discard all changes queued on close.
In the end it looks like I was using the wrong approach.... In JBoss you can`t (better said, I could not get to) access JPA directly (as you would do in JSE).
I ended creating an EJB (with transactions) and passing all JPA logic there.
PS: Of course, if I am wrong please tell me (now it is more of an academic issue, but still I want to know)

How to make CXF SOAP Request to be printed under log file

#InInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingInInterceptor" )
#OutInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingOutInterceptor")
public class SKTWeb implements SKTWebService {
// method logic goes here
}
Hi , after adding these two lines inside the CXF Method Implementation .
I could get whip of SOAP Requestand Response under tomcat server console
see a instance of SOAP Request Printed under Tomcat console
INFO: Inbound Message
----------------------------
ID: 1
Address: /Sktweb-33.0/services/SKTWeb
Encoding: UTF-8
Content-Type: text/xml; charset=UTF-8
Headers: {cache-control=[no-cache], content-type=[text/xml; charset=UTF-8], connection=[keep-alive], host=[local
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns4:strategy xmlns:ns
Could anybody please tell me how can get this inside my Log file (Log4j)
Currently this is my log4j.properties file
log4j.rootCategory=INFO, A1
# A1 is a DailyRollingFileAppender
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.file=/Haieeee.log
log4j.appender.A1.datePattern='.'yyyy-MM-dd
log4j.appender.A1.append=true
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-22d{dd/MMM/yyyy HH:mm:ss} - %m%n
And also i have META-INF\cxf\org\apache\cxf\Logger Log4jLogger.class inside the Web Application .
And also i kept
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
Inside the endpoints.xml file
Any help please
A slight bit of confusion it seems. You need your assembled application to have a locatable file META-INF/cxf/org.apache.cxf.Logger (yes, those are dots! It's not a .java or .class file) and it should have the contents:
org.apache.cxf.common.logging.Log4jLogger
I use exactly the above in my code and it works like a charm. (I don't use it with the message logging feature though; too much traffic when deployed for my tasteā€¦)
Basically you want your properties file to be picked by CXF then it use this properties file instead of CXF's.
I am using spring configuration in my CXF application. If you are not using any Spring config then you create a new config and load it on start up using spring context listener, then you can add the below code in your XML file.
<bean id="log4jInitialization"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
<property name="targetMethod" value="initLogging" />
<property name="arguments">
<list>
<value>file:fullpath/filename.properties</value>
</list>
</property>
</bean>
You can also have classpath:filename.properties in the <list> </list>. The logging implemented in Spring framework will be used to log all the request and response. You can also use the same logging implementation to use in your application.
Always go with interceptors...Add slf4j-log4j12-1.6.1.jar,slf4j-api-1.6.1.jar and commons-logging-1.1.1.jar. Paste the following code in your cxf.xml...
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" id="loggingInInterceptor" />
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" id="logOutInterceptor" />
<cxf:bus>
<cxf:inInterceptors>
<ref bean="loggingInInterceptor" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="logOutInterceptor" />
</cxf:outInterceptors>
</cxf:bus>

Resources