Posts Tagged ‘Spring’
Problem: Spring JMS MessageListener Stuck / Not Receiving Messages
Scenario
A Spring Boot application using ActiveMQ with @JmsListener
suddenly stops receiving messages after running for a while. No errors in logs, and the queue keeps growing, but the consumers seem idle.
Setup
-
ActiveMQConnectionFactory
was used. -
The queue (
myQueue
) was filling up. -
Restarting the app temporarily fixed the issue.
Investigation
-
Checked ActiveMQ Monitoring (Web Console)
-
Messages were enqueued but not dequeued.
-
Consumers were still active, but not processing.
-
-
Thread Dump Analysis
-
Found that listener threads were stuck in a waiting state.
-
The problem only occurred under high load.
-
-
Checked JMS Acknowledgment Mode
-
Default
AUTO_ACKNOWLEDGE
was used. -
Suspected an issue with message acknowledgment.
-
-
Enabled Debug Logging
-
Added:
-
Found repeated logs like:
-
This hinted at connection issues.
-
-
Tested with a Different Message Broker
-
Using Artemis JMS instead of ActiveMQ resolved the issue.
-
Indicated that it was broker-specific.
-
Root Cause
ActiveMQ’s TCP connection was silently dropped, but the JMS client did not detect it.
-
When the connection is lost,
DefaultMessageListenerContainer
doesn’t always recover properly. -
ActiveMQ does not always notify clients of broken connections.
-
No exceptions were thrown because the connection was technically “alive” but non-functional.
Fix
-
Enabled
keepAlive
in ActiveMQ connection -
Forced Reconnection with Exception Listener
-
Implemented:
-
This ensured that if a connection was dropped, the listener restarted.
-
-
Switched to
DefaultJmsListenerContainerFactory
withDMLC
-
SimpleMessageListenerContainer
was less reliable in handling reconnections. -
New Configuration:
-
Final Outcome
✅ After applying these fixes, the issue never reoccurred.
🚀 The app remained stable even under high load.
Key Takeaways
-
Silent disconnections in ActiveMQ can cause message listeners to hang.
-
Enable
keepAlive
andoptimizeAcknowledge
for reliable connections. -
Use
DefaultJmsListenerContainerFactory
withDMLC
instead ofSMLC
. -
Implement an
ExceptionListener
to restart the JMS connection if necessary.
🚀 Making Spring AOP Work with Struts 2: A Powerful Combination! 🚀
Spring AOP (Aspect-Oriented Programming) and Struts 2 might seem like an unusual pairing, but when configured correctly, they can bring cleaner, more modular, and reusable code to your Struts-based applications.
The Challenge:
- Struts 2 manages its own action instances for each request, while Spring’s AOP relies on proxying beans managed by the Spring container. This means Struts actions are not Spring beans by default, making AOP trickier to apply.
- The Solution: Making Struts 2 Actions Spring-Managed
- To make Spring AOP work with Struts 2, follow these steps:
✅ Step 1: Enable Spring integration with Struts 2
Ensure your `struts.xml` is configured to use Spring:
“`<constant name=”struts.objectFactory” value=”spring”/>“`
This makes Struts retrieve action instances from the Spring context instead of creating them directly.
✅ Step 2: Define Actions as Spring Beans
In your applicationContext.xml or equivalent Spring configuration, define your Struts actions:
“`
<bean id=”myAction” class=”com.example.MyStrutsAction” scope=”prototype”/>
“`
Setting the scope to “prototype” ensures a new instance per request, preserving Struts 2 behavior.
✅ Step 3: Apply AOP with `@Aspect`
Now, you can apply Spring AOP to your Struts actions just like any other Spring-managed bean:
“`
@Aspect
@Component
public class LoggingAspect {
@Before(“execution(* com.example.MyStrutsAction.execute(..))”)
public void logBefore(JoinPoint joinPoint) {
System.out.println(“Executing: ” + joinPoint.getSignature().toShortString());
}
}
“`
This will log method executions before any `execute()` method in your actions runs!
Key Benefits of This Approach
🔹 Separation of Concerns – Keep logging, security, and transaction management outside your action classes.
🔹 Reusability – Apply cross-cutting concerns like security or caching without modifying Struts actions.
🔹 Spring’s Full Power – Leverage dependency injection and other Spring features within your Struts 2 actions.
🔥 By integrating Spring AOP with Struts 2, you get the best of both worlds: Struts’ flexible request handling and Spring’s powerful aspect-oriented capabilities. Ready to make your legacy Struts 2 app cleaner and more maintainable? Let’s discuss!
[Spring I/O 2023] Do You Really Need Hibernate?
Simon Martinelli’s thought-provoking session at Spring I/O 2023 challenges the default adoption of Hibernate in Java applications. With decades of experience, Simon advocates for jOOQ as a performant, SQL-centric alternative for database-centric projects. Using a track-and-field event management system as a case study, he illustrates how jOOQ simplifies data access, avoids common ORM pitfalls, and complements Hibernate when needed. This presentation is a masterclass in rethinking persistence strategies for modern Java development.
Questioning the ORM Paradigm
Simon begins by questioning the reflexive use of Hibernate and JPA in Java projects. While powerful for complex domain models, ORMs introduce overhead—such as dirty checking or persistence by reachability—that may not suit all applications. For CRUD-heavy systems, like his 25-year-old event management application, a simpler approach is often sufficient. By focusing on database tables rather than object graphs, developers can streamline data operations, avoiding the complexity of managing entity state transitions.
jOOQ: A Database-First Approach
jOOQ’s database-first philosophy is central to Simon’s argument. By generating type-safe Java code from database schemas, jOOQ enables developers to write SQL-like queries using a fluent DSL. This approach, as Simon demonstrates, ensures compile-time safety and eliminates runtime errors from mismatched SQL strings. The tool supports a wide range of databases, including legacy systems with stored procedures, making it versatile for both modern and enterprise environments. Integration with Flyway and Testcontainers further simplifies schema migrations and code generation.
Efficient Data Retrieval with Nested Structures
A highlight of Simon’s talk is jOOQ’s ability to handle nested data structures efficiently. Using the event management system’s ranking list—a tree of competitions, categories, athletes, and results—he showcases jOOQ’s MULTISET
feature. This leverages JSON functionality in modern databases to fetch hierarchical data in a single SQL statement, avoiding the redundancy of JPA’s join fetches. This capability is particularly valuable for REST APIs and reporting, where nested data is common, eliminating the need for DTO mapping.
Combining jOOQ and Hibernate for Flexibility
Rather than advocating for jOOQ as a complete replacement, Simon proposes a hybrid approach. jOOQ excels in querying, bulk operations, and legacy database integration, while Hibernate shines in entity state management and cascading operations. By combining both in a single application, developers can leverage their respective strengths. Simon warns against using JPA for raw SQL, as it lacks jOOQ’s type safety, reinforcing the value of choosing the right tool for each task.
Practical Insights and Tooling
Simon’s demo, backed by a GitHub repository, illustrates jOOQ’s integration with Maven, Testcontainers, and a new Testcontainers Flyway plugin. He highlights practical considerations, such as whether to version generated code and jOOQ’s licensing model for commercial databases. The talk also addresses limitations, like MULTISET
’s incompatibility with MariaDB, offering candid advice for database selection. These insights ground the presentation in real-world applicability, making it accessible to developers of varying experience levels.
A Call to Rethink Persistence
Simon’s presentation is a compelling call to reassess persistence strategies. By showcasing jOOQ’s performance and flexibility, he encourages developers to align their tools with application needs. His track-and-field application, evolved over decades, serves as a testament to the enduring value of SQL-driven development. For Java developers seeking to optimize data access, this talk offers a clear, actionable path forward, blending modern tooling with pragmatic wisdom.
Links:
Hashtags: #SpringIO2023 #jOOQ #Hibernate #Java #SQL #Database #SimonMartinelli #Testcontainers #Flyway
[Spring I/O 2023] Multitenant Mystery: Only Rockers in the Building by Thomas Vitale
In the vibrant atmosphere of Spring I/O 2023, Thomas Vitale, a seasoned software engineer and cloud architect at Systematic in Denmark, captivated the audience with his exploration of multitenant architectures in Spring Boot applications. Through a compelling narrative involving a stolen guitar in a building inhabited by rock bands, Thomas unraveled the complexities of ensuring data isolation, security, and observability in multi-tenant systems. His presentation, rich with practical insights and live coding, offered a masterclass in building robust SaaS solutions using Java, Spring, and related technologies.
Understanding Multitenancy
Thomas began by defining multitenancy as an architecture where a single application instance serves multiple clients, or tenants, simultaneously. This approach, prevalent in software-as-a-service (SaaS) solutions, optimizes operational costs by sharing infrastructure across customers. He illustrated this with an analogy of a building housing rock bands, where each band (tenant) shares common facilities like staircases but maintains private storage for their instruments. This setup underscores the need for meticulous data isolation to prevent cross-tenant data leakage, a critical concern in industries like healthcare where regulatory compliance is paramount.
Implementing Tenant Resolution
A cornerstone of Thomas’s approach was establishing a tenant context within a Spring Boot application. He demonstrated how to resolve tenant information from HTTP requests using a custom header, X-Tenant-ID
. By implementing a tenant resolver and interceptor, Thomas ensured that each request’s tenant identifier is stored in a thread-local context, accessible throughout the request lifecycle. His live coding showcased the integration of Spring MVC’s HandlerInterceptor
to seamlessly extract and manage tenant data, setting the stage for further customization. This mechanism allows developers to process requests in a tenant-specific manner, enhancing the application’s flexibility.
Data Isolation Strategies
Data isolation emerged as the most critical aspect of multitenancy. Thomas outlined three strategies: discriminator-based partitioning, separate schemas, and separate databases. He focused on the separate schema approach, leveraging Hibernate and Spring Data JPA to manage tenant-specific schemas within a single PostgreSQL database. By configuring Hibernate’s CurrentTenantIdentifierResolver
and MultiTenantConnectionProvider
, Thomas ensured that database connections dynamically switch schemas based on the tenant context. His demo highlighted the effectiveness of this strategy, showing how instruments stored for one tenant (e.g., “Dukes”) remained isolated from another (“Beans”), thus safeguarding data integrity.
Security and Observability
Security and observability were pivotal in Thomas’s narrative. He addressed the challenge of dynamic authentication by integrating Keycloak, allowing tenant-specific identity providers to be resolved at runtime. This approach avoids hardcoding configurations, enabling seamless onboarding of new tenants. For observability, Thomas emphasized the importance of tenant-specific logging, metrics, and tracing. Using Micrometer and OpenTelemetry, he enriched logs and traces with tenant identifiers, facilitating debugging and monitoring. A critical lesson emerged during his demo: a caching oversight led to data leakage across tenants, underscoring the need for tenant-specific cache keys. Thomas resolved this by implementing a custom key generator, restoring data isolation.
Solving the Mystery
The stolen guitar mystery served as a metaphor for real-world multitenancy pitfalls. By tracing the issue to a caching flaw, Thomas illustrated how seemingly minor oversights can have significant consequences. His resolution—ensuring tenant-specific caching—reinforced the importance of vigilance in multi-tenant systems. The presentation concluded with a call to prioritize data isolation, offering attendees a blueprint for building scalable, secure SaaS applications with Spring Boot.
Links:
- Thomas Vitale on LinkedIn
- Systematic company website
- Thomas Vitale’s GitHub repository
- Thomas Vitale’s book: Cloud Native Spring in Action
Hashtags: #Multitenancy #SpringBoot #Java #SaaS #DataIsolation #Security #Observability #ThomasVitale #Systematic #Keycloak #Hibernate #SpringIO2023
[Spring I/O 2023] Managing Spring Boot Application Secrets: Badr Nass Lahsen
In a compelling session at Spring I/O 2023, Badr Nasslahsen, a DevSecOps expert at CyberArk, tackled the critical challenge of securing secrets in Spring Boot applications. With the rise of cloud-native architectures and Kubernetes, secrets like database credentials or API keys have become prime targets for attackers. Badr’s talk, enriched with demos and real-world insights, introduced CyberArk’s Conjur solution and various patterns to eliminate hard-coded credentials, enhance authentication, and streamline secrets management, fostering collaboration between developers and security teams.
The Growing Threat to Application Secrets
Badr opened with alarming statistics: in 2021, software supply chain attacks surged by 650%, with 71% of organizations experiencing such breaches. He cited the 2022 Uber attack, where a PowerShell script with hard-coded credentials enabled attackers to escalate privileges across AWS, Google Suite, and other systems. Using the SALSA threat model, Badr highlighted vulnerabilities like compromised source code (e.g., Okta’s leaked access token) and build processes (e.g., SolarWinds). These examples underscored the need to eliminate hard-coded secrets, which are difficult to rotate, track, or audit, and often exposed inadvertently. Badr advocated for “shifting security left,” integrating security from the design phase to mitigate risks early.
Introducing Application Identity Security
Badr introduced the concept of non-human identities, noting that machine identities (e.g., SSH keys, database credentials) outnumber human identities 45 to 1 in enterprises. These secrets, if compromised, grant attackers access to critical resources. To address this, Badr presented CyberArk’s Conjur, an open-source secrets management solution that authenticates workloads, enforces policies, and rotates credentials. He emphasized the “secret zero problem”—the initial secret needed at application startup—and proposed authenticators like JWT or certificate-based authentication to solve it. Conjur’s attribute-based access control (ABAC) ensures least privilege, enabling scalable, auditable workflows that balance developer autonomy and security requirements.
Patterns for Securing Spring Boot Applications
Through a series of demos using the Spring Pet Clinic application, Badr showcased five patterns for secrets management in Kubernetes. The API pattern integrates Conjur’s SDK, using Spring’s @Value
annotations to inject secrets without changing developer workflows. The Secrets Provider pattern updates Kubernetes secrets from Conjur, minimizing code changes but offering less security. The Push-to-File pattern stores secrets in shared memory, updating application YAML files securely. The Summon pattern uses a process wrapper to inject secrets as environment variables, ideal for apps relying on such variables. Finally, the Secretless Broker pattern proxies connections to resources like MySQL, hiding secrets entirely from applications and developers. Badr demonstrated credential rotation with zero downtime using Spring Cloud Kubernetes, ensuring resilience for critical applications.
Enhancing Kubernetes Security and Auditing
Badr cautioned that Kubernetes secrets, being base64-encoded and unencrypted by default, are insecure without etcd encryption. He introduced KubeScan, an open-source tool to identify risky roles and permissions in clusters. His demos highlighted Conjur’s auditing capabilities, logging access to secrets and enabling security teams to track usage. By centralizing secrets management, Conjur eliminates “security islands” created by disparate tools like AWS Secrets Manager or Azure Key Vault, ensuring compliance and visibility. Badr stressed the need for a federated governance model to manage secrets across diverse technologies, empowering developers while maintaining robust security controls.
Links:
Hashtags: #SecretsManagement #SpringIO2023 #SpringBoot #CyberArk #BadrNassLahsen
MultiException[java.lang.RuntimeException: Error scanning file]
Case
I run a project with JSF 2 / PrimeFaces 5 (BTW: it rocks!) / Spring 4 / Jetty 9 / Java 8:
[java]MultiException java.lang.RuntimeException: Error scanning file SummerBean.class, java.lang.RuntimeException: Error scanning entry …/SummerService.class from jar file:/…/spring-tier-1.0-SNAPSHOT.jar, java.lang.RuntimeException: Error scanning entry …/SummerServiceImpl.class from jar file:/…/spring-tier-1.0-SNAPSHOT.jar
at org.eclipse.jetty.annotations.AnnotationConfiguration.scanForAnnotations(AnnotationConfiguration.java:530)[/java]
Explanation
The error occurs because of a conflict on the JARs of ASM.
Fix
You have to override Jetty’s dependencies to ASM.
In Maven’s POM, amend Jetty plugin to force ASM versions:
[xml]<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>5.0.2</version>
</dependency>
</dependencies>
<!– … –>
</plugin>
[/xml]
Then it should work 😉
Retour sur Devoxx FR 2013
J’ai eu la chance d’assister a la derniere journee de DevoxxFR a Paris, le vendredi 29/03/2013, pour le compte de mon employeur StepInfo, sponsor de l’evenement. Voici quelques impressions en vrac
General
- C’est bien organise, il y a du monde, et excepte au moment du depart au niveau des vestiaires, il n’y a pas eu de gros souci de logistique.
- Les entreprises sponsors ont joue le jeu 😉
- Que ce soit au niveau des stands ou des conferences, la domination des Mac est ecrasante! Google a reussi a mettre en valeur ses ChromeBooks, mais j’ai vu peu de Windows et encore moins de Linux.
- J’ai pu assister a 4 conferences, toutes interessantes, mais d’un niveau heterogene, je reviens dessus plus en detail ci-dessous.
IDE Java : astuces de productivité pour le quotidien
La conference est animee par Xavier Hanin (@xavierhanin). Il y presente les trois IDE phares du monde Java: NetBeans, Eclipse et IntelliJ IDEA.
Maitrisant plutot bien IDEA, je n’ai pas appris de choses fondamentales sur mon IDE, si ce n’est le raccourci Ctrl+Shift+A
pour afficher les intentions. J’ai connu NetBeans a ses debuts (Forte puis Sun ONE), mais j’en ai totalement perdu la maitrise depuis des annees. Quant a Eclipse, il m’arrive de le lancer quelques fois par an pour des problematiques clients specifiques, mais je suis contraint d’avoir recours a la souris en quasi-permanence ; sous IDEA c’est tres rare.
Un “sondage” assez grossier des personnes dans la salle a donne des resultats interessants: ~15% des developpeurs presents utilisent NetBeans, ~25% IDEA et ~90/95% Eclipse.
Quick Start avec le Cloud Google
La conference est animee par Didier Girard de SFEIR et Alexis Moussine-Pouchkine de Google France. Les principaux outils de Google pour le cloud sont presentes, en prenant pour hypothese de creer une startup: une solution “a l’ancienne”, avec serveurs d’applications, gestion materielle etc. est avancee, avant de ceder la place a une solution entierement sur le cloud de Google.
En un mot: c’est tres convaincant.
Je regrette que le sujet n’ait pas ete elargi vers des solutions cloud alternatives, comme celle d’Amazon.
- Didier Girard:
- Sur twitter: @DidierGirard
- Sur Google+: +Didier
- Alexis Moussine-Pouchkine:
- Blog: http://alexismp.wordpress.com/
- Twitter: @alexismp
- Google+: +Alexis
The Spring Update: Looking at Spring 3.1, 3.2, and 4.0
La presentation est menee par Josh Long de SpringSource. On se rend compte tres rapidement que ne serait-ce que pour la qualite du show, nous les Francais (voire les Latins) nous sommes largement en dessous de la qualite des Anglo-Saxons.
Josh enonce ses concepts, donne des exemples, met l’eau a la bouche. Au bout de 50′ de conference, je n’ai plus qu’une envie: retourner coder avec les dernieres versions de Spring!
Parmi toutes les nouveautes, j’en retiens deux:
- l’
AnnotationConfigApplicationContext
, qui m’evitera de taper d’ecrire un bloc comme:[xml] <context:component-scan annotation-config="true" base-package="lalou.jonathan.beans"/>[/xml] - l’integration future des websockets d’HTML5 pour obeir a la norme JEE7 d’ici la fin de l’annee.
Ce dernier point m’interesse particulierement, en raison d’un projet sur lequel je travaille actuellement, et dont nombre de problemes seraient resolus par les websockets de JEE7. Theoriquement, et potentiellement, d’ici la fin de l’annee 2013, nous pourrions integrer une brique “Spring JEE7” avec websocket au sein d’un WebSphere 8 (donc non JEE7-compliant), au lieu d’etre dependant dans la prochaine release du serveur d’applications d’IBM.
Josh:
- sur twitter: @starbuxman
- sur son blog: http://joshlong.com/
- Google+: +Josh
Entre HPC et big data: un case study sur la simulation du risque de contrepartie
C’est la conference dont j’ai vu le moins le rapport avec Devoxx, mais ayant passe 7 ans dans la finance de marche j’y ai trouve mon interet. En passant, j’y ai vu le seul PC sous Windows de toutes les conferences :-D.
Le theme de cette conference est: comment deporter une partie du calcul intensif de Monte-Carlo du CPU vers les GPU? Ces derniers ont une taille et une structure de memoire radicalement differente de celles des CPU (CPU+RAM pour etre plus precis). Les GPU permettent d’effectuer des masses de calcul en un temps bien plus faible (jusqu’a 99% de gain) qu’en architecture classique, moyennant une reecriture du code C en un autre langage adapte, par exemple OpenCL.
Les deux speakers, de Murex, sont Adrien Tay Pamart (visiblement pas tres a l’aise en mode geek) et Jonathan Lellouche pour la partie technique.
Durant les questions, l’existence de ponts Java vers OpenCL, comme JavaCL est evoquee. Il est dommage de ne pas avoir plus de temps pour creuser ce theme.
5 ans et 500 releases en 50 minutes !
La presentation est dirigee par Freddy Mallet et Olivier Gaudin de Sonar.
La demonstration est rudement bien faite. Les dirigeant de SonarSource retracent, dans un ordre plus ou moins chronologique, les problemes, ou les impediments a-t-on envie de dire, rencontres en 5 ans sur Sonar.
Quelques themes forts: le context switching est une plaie, on ne gere pas une entreprise commerciale avec des clients comme un simple projet open source, etc.
- Freddy:
- Sur twitter: @FreddyMallet
- Olivier:
- Sur twitter: @gaudol
En guise de conclusion
Devoxx a repondu aux attentes que j’avais en y entrant:
- une journee de formation intensive et motivante
- revoir des “anciennes tetes”
- echanger des cartes de visite
Qu’il me soit donc permis ici de remercier StepInfo pour m’avoir permis d’acceder a cette journee, ainsi que les organisateurs de Devoxx pour le travail qu’il ont accompli.
Vivement DevoxxFR 2014!
Unable to instantiate default tuplizer… java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.
Case
On running a web application hosted on Jetty, I get the following stracktrace:
[java]Nested in org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’ defined in ServletContext resource [/WEB-INF/classes/config/spring/beans/HibernateSessionFactory.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]:
java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.<init>(I)V[/java]
Unlike what I immediatly thought at first glance, the problem is not induced by the Tuplizer ; the actual error is hidden at the bottom: java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter.
Here are some of the dependencies:
[java]org.hsqldb:hsqldb:jar:2.2.8:compile
org.springframework:spring:jar:2.5.6:compile
org.hibernate:hibernate:jar:3.2.7.ga:compile
javax.transaction:jta:jar:1.0.1B:compile
| +- asm:asm-attrs:jar:1.5.3:compile
| \- asm:asm:jar:1.5.3:compile[/java]
Fix
Main fix
The case is a classic problem of inherited depencencies. To fix it, you have to excluse ASM 1.5.3, and replace it with more recent version. In the pom.xml
, you would then have:
[xml]
<properties>
<spring.version>3.1.0.RELEASE</spring.version>
<hibernate.version>3.2.7.ga</hibernate.version>
<asm.version>3.1</asm.version>
</properties>
…
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm-attrs</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>
[/xml]
Other improvements
I took the opportunity to upgrade Spring 2.5 to Spring 3.1 (cf the properties above).
Besides, I modified the *.hbm.xml files to use object types, rather than primary types, eg replacing:
[xml]<id name="jonathanId" type="long">[/xml]
with:
[xml]<id name="jonathanId" type="java.lang.Long">[/xml]
How to export Oracle DB content to DBUnit XML flatfiles?
Case
From an Agile and TDD viewpoint, performing uni tests on DAO is a requirement. Sometimes, instead of using DBUnit datasets “out of the box”, the developper need test on actual data. In the same vein, when a bug appears on production, isolating and reproducing the issue is a smart way to investigate, and, along the way, fix it.
Therefore, how to export actual data from Oracle DB (or even MySQL, Sybase, DB2, etc.) to a DBUnit dataset as a flat XML file?
Here is a Runtime Test I wrote on this subject:
Fix
Spring
Edit the following Spring context file, setting the login, password, etc.
[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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!– don’t forget to write this, otherwise the application will miss the driver class name, and therfore the test will fail–>
<bean id="driverClassForName" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="java.lang.Class"/>
<property name="targetMethod" value="forName"/>
<property name="arguments">
<list>
<value>oracle.jdbc.driver.OracleDriver</value>
</list>
</property>
</bean>
<bean id="connexion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
depends-on="driverClassForName">
<property name="targetClass" value="java.sql.DriverManager"/>
<property name="targetMethod" value="getConnection"/>
<property name="arguments">
<list>
<value>jdbc:oracle:thin:@host:1234:SCHEMA</value>
<value>myLogin</value>
<value>myPassword</value>
</list>
</property>
</bean>
<bean id="databaseConnection" class="org.dbunit.database.DatabaseConnection">
<constructor-arg ref="connexion"/>
</bean>
<bean id="queryDataSet" class="org.dbunit.database.QueryDataSet">
<constructor-arg ref="databaseConnection"/>
</bean>
</beans>[/xml]
The bean driverClassForName
does not look to be used ; anyway, if Class.forName("oracle.jdbc.driver.OracleDriver")
is not called, then the test will raise an exception.
To ensure driverClassForName
is created before the bean connexion, I added a attribute depends-on="driverClassForName"
. The other beans will be created after connexion
, since Spring will deduce the needed order of creation via the explicit dependency tree.
Java
[java]public class Oracle2DBUnitExtractor extends TestCase {
private QueryDataSet queryDataSet;
@Before
public void setUp() throws Exception {
final ApplicationContext applicationContext;
applicationContext = new ClassPathXmlApplicationContext(
"lalou/jonathan/Oracle2DBUnitExtractor-applicationContext.xml");
assertNotNull(applicationContext);
queryDataSet = (QueryDataSet) applicationContext.getBean("queryDataSet");
}
@Test
public void testExportTablesInFile() throws DataSetException, IOException {
// add all the needed tables ; take care to write them in the right order, so that you don’t happen to fall on dependencies issues, such as ones related to foreign keys
queryDataSet.addTable("MYTABLE");
queryDataSet.addTable("MYOTHERTABLE");
queryDataSet.addTable("YETANOTHERTABLE");
// Destination XML file into which data needs to be extracted
FlatXmlDataSet.write(queryDataSet, new FileOutputStream("myProject/src/test/runtime/lalou/jonathan/output-dataset.xml"));
}
}[/java]
Spring / Mule / CheckExclusiveAttributesException: The attributes of Element … do not match the exclusive groups …
Case
I have the following block in my Mule config file:
[xml]<servlet:inbound-endpoint path="authenticationService" address="http://localhost:1234">[/xml]
. Even though this block matches XSD constraints, it is illegal from a functionnal point of view.
I get the following stacktrace:
[java]Offending resource: mule-config.xml; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [lalou/jonathan/mule-config.xml]; nested exception is org.mule.config.spring.parsers.processors.CheckExclusiveAttributes$CheckExclusiveAttributesException: The attributes of Element servlet:inbound-endpoint{address=http://localhost:1234, name=.authenticationService:inbound.157:inbound-endpoint.158, path=authenticationService} do not match the exclusive groups [address] [ref] [path][/java]
Explanation and Fix
The exception is meaningful: for the tag <servlet:inbound-endpoint
>, only one among the three following attributes is needed: path, ref and address.
To fix the issue, keep only the relevant attribute.