Testing JNDI Spring Websphere Outside the Container - spring

I have successfully tested some DAO outside a weblogic server by looking up the datasource information through jndi. I have search for a similar option with websphere and have to yet come accross a solution that does not involve hardcoding the username and password in some location within the application or something similar. Right now my jndi settings look like this inside spring:
<bean id="applicationServerEnviromentProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties"><props>
<prop key="java.naming.factory.initial">com.ibm.websphere.naming.WsnInitialContextFactory</prop>
<prop key="java.naming.provider.url">iiop://localhost:2809</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>PeopleAppDS</value></property>
<property name="jndiEnvironment"><ref local="applicationServerEnviromentProperties"/></property>
</bean>
I have Tested the jndi connection and it is working when the application is loaded on to websphere. I would like to be able to test the daos inside eclipse for instance before the app is loaded. Any help would be much appreciated.
Here are the details for the test case.
-------BaseTestCase.java--------------------
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations= {"file:data-access-config.xml"})
public class BaseTestCase {
}
-----PersonDaoTest.java----------------
import static org.junit.Assert.assertNotNull;
import java.util.List;<br>
import org.junit.Test;<br>
import org.springframework.beans.factory.annotation.Autowired;
import ....dao.PersonDao;<br>
import ....domain.Person;<br>
public class PersonDaoTest extends BaseTestCase {
#Autowired
private PersonDao personDao;
#Test
public void findByName() {
List<Person> people = personDao.listByName("j%", false, "userId");
assertNotNull(people);
}
}

The right way to do it is to have a JNDI data source with a DriverManagerDataSource default. If you run in the container, Spring will use the named data source; if the lookup fails, it'll use the non-JNDI data source.

Related

How to start HSQLDB in server mode from Spring boot application

I have a Spring boot application, running with jpa data and hsqldb 2.3.3 (in Centos 7), the application runs fine but I would like to use HSQLDB database manager to check the data status, however it failed:
application.properties:
spring.datasource.url=jdbc:hsqldb:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
Command to start HSQLDB:
java -cp /home/mycentos/.m2/repository/org/hsqldb/hsqldb/2.3.3/hsqldb-2.3.3.jar org.hsqldb.util.DatabaseManagerSwing
If I tried to log in with HSQLDB server mode, it pops Connection refused error
jdbc:hsqldb:hsql://localhost/testdb
If I tried to log in in-memory db, I can log in but no table and data showing up
jdbc:hsqldb:hsql:testdb
Question:
How to make it works?
Do I have to refer to the hsqldb.jar from tomcat deployment folder because that is the one using by the application?
Any configuration difference to configure hsqldb in server mode or in-memory mode from Spring application?
Can any method make in-memory mode working in such situation (to check data by db created Spring boot)?
To access the HSQL DB created by Spring boot app, you have to start HSQL server. For example, create a XML configuration file hsql_cfg.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.xsd">
<bean id="hqlServer" class="org.hsqldb.server.Server" init-method="start" destroy-method="stop">
<property name="properties"><bean class="org.hsqldb.persist.HsqlProperties">
<constructor-arg><props>
<prop key="server.database.0">mem:testdb</prop>
<prop key="server.dbname.0">testdb</prop><!--DB name for network connection-->
<prop key="server.no_system_exit">true</prop>
<prop key="server.port">9001</prop><!--default port is 9001 -->
</props></constructor-arg>
</bean></property>
</bean>
</beans>
Here is a example to import the XML configuration in main application class.
#SpringBootApplication
#ImportResource(value="classpath:/package/hsql_cfg.xml")
public class MyApplication {
}
The HSQL server will start with Spring boot app. Other applications could connect to the HSQL server using JDBC url
jdbc:hsqldb:hsql://ip_address:port/testdb
Of course, hsqldb.jar is required for loading JDBC driver class.
Just to add to beckyang's answer, here is my approach.
Includes a hack to redirect logs to slf4j.
Includes specifying a corresponding datasource.
import org.hsqldb.jdbc.JDBCDataSource;
import org.hsqldb.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
#Configuration
public class DataSourceConfiguration {
private final Logger log = LoggerFactory.getLogger(getClass());
#Bean(initMethod = "start", destroyMethod = "stop")
#ConfigurationProperties//(prefix = "alarms.idempotent.server")
public Server idempotentServer(#Value("${alarms.idempotent.server.path}") String path, #Value("${alarms.idempotent.port}") int port, #Value("${alarms.idempotent.name}") String name) {
Server server = new Server();
server.setDatabaseName(0, name);
server.setDatabasePath(0, path);
server.setPort(port);
server.setLogWriter(slf4jPrintWriter());
server.setErrWriter(slf4jPrintWriter());
return server;
}
#Bean("idempotentDataSource")
#Primary
#ConfigurationProperties
public DataSource idempotentDataSource(#Value("${alarms.idempotent.datasource.url}") String urlNoPath, #Value("${alarms.idempotent.name}") String name) {
JDBCDataSource jdbcDataSource = new JDBCDataSource();
String url = urlNoPath;
if (!url.endsWith("/")) {
url += "/";
}
url += name;
jdbcDataSource.setUrl(url);
jdbcDataSource.setUser("sa");
return jdbcDataSource;
}
private PrintWriter slf4jPrintWriter() {
PrintWriter printWriter = new PrintWriter(new ByteArrayOutputStream()) {
#Override
public void println(final String x) {
log.debug(x);
}
};
return printWriter;
}
}

How to register a package of Formatters in Spring MVC

let's say I have 200 formatters contained in one package. How can I register a package of formatters instead of doing this:
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<ref bean="MyFormatter1" />
<ref bean="MyFormatter2" />
...
<ref bean="MyFormatter200" />
</set>
</property>
</bean>
I would try to use java configuration for that:
import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addFormatters(FormatterRegistry registry) {
for (Formatter formatter : collectFormatters()) {
registry.addFormatter(formatter);
}
}
}
Now you need to implement collectFormatters method. I don't know the details of your application so there maybe many different ways to do it:
1) you could put #Component annotation to all formatters, add this package to autoscanning, so Spring will initialize them and add to the application context. After that you can just inject them like this: #Resource List<Formatter> formatters.
2) you could write some logic for inspecting the package by yourself (I suggest to look at how Spring doing this).

Null Pointer with Spring #Autowired

I am new to Spring & Hibernate and I have spent a couple of weeks trying to get to grips with it. Most of my experience is with Oracle development so this is a departure for me. Hibernate is working but Spring is giving me a headache.
I tried following this tutorial but using an Oracle db and my Address table.
http://www.codejava.net/frameworks/spring/spring-4-and-hibernate-4-integration-tutorial-part-1-xml-configuration
The web page wasn't working so I tried a test case on the HomeController.java That didn't work so but I believe I have narrowed it down to a null pointer in addressDao and so I wrote a test case for that to try to pin it down.
java.lang.NullPointerException: null
springexp.unittest.AddressDaoTest.testListAddr(AddressDaoTest.java:29)
package springexp.unittest;
import bussys.model.Address;
import springexp.dao.AddressDao;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
public class AddressDaoTest
{
#Autowired
private AddressDao addressDao;
#RequestMapping(value="/")
/**
* #see springexp.dao.AddressDao#listAddr()
*/
#Test
public void testListAddr()
{
List<Address> listAddresses = addressDao.listAddr(); << error thrown here
System.out.println(listAddresses.get(1).getFirstname());
fail("Unimplemented");
}
}
I have also spent a long time reading stackoverflow and others to try to fix the null pointer issue but there seems to be lots of ways of writing this and it has changed in various versions.
In servlet-context.xml I have this:
<!-- Hibernate Session Factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>springexp.dao.AddressDao</value>
</list>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="addressDao" class="springexp.dao.AddressDaoImpl">
<constructor-arg>
<ref bean="sessionFactory" />
</constructor-arg>
</bean>
<!-- added this recently based on one suggestion -->
<bean id="addressDaoTest" class="springexp.unittest.AddressDaoTest">
<constructor-arg>
<ref bean="sessionFactory" />
</constructor-arg>
</bean>
AddressDaoImpl.java
package springexp.dao;
import bussys.model.Address;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;
public class AddressDaoImpl
implements AddressDao
{
private SessionFactory sessionFactory;
public AddressDaoImpl(SessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
#Override
#Transactional
public List<Address> listAddr()
{
#SuppressWarnings("unchecked")
List<Address> listAddress = (List<Address>)
sessionFactory.getCurrentSession().createCriteria(Address.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
return listAddress;
}
}
I hope this is enough to give a clue to my mistake(s).

SPRING, JPA(EclipseLink) with JTA Transaction Manager(JBoss 7) - NOT Committing to Database

I have created an example - SPRING, JPA(EclipseLink persistence provider) with JTA Transaction Manager(JBoss 7). I have observed that all the data in database is being shown in UI properly for the read operations. But when it comes to save/update or delete operation the services layer is not committing the work to database. No exception is caught(I have checked the console/log too and also debugged the code where I can see entityManager.persist/remove is being invoked without any exception).
--Code Listing--
1. Datasource configuration in standalone.xml
<datasource jta="true" jndi-name="java:/mysql_customerdb3" pool-name="mysql_customerdb3_pool" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:mysql://localhost:3306/customerdb</connection-url>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
<password>root</password>
</security>
<statement>
<prepared-statement-cache-size>10</prepared-statement-cache-size>
<share-prepared-statements>true</share-prepared-statements>
</statement>
</datasource>
<drivers>
<driver name="mysql" module="com.mysql">
<driver-class>com.mysql.jdbc.Driver</driver-class>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
</driver>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
Database driver configuration in module.xml
persistence.xml
org.eclipse.persistence.jpa.PersistenceProvider
java:/mysql_customerdb3
com.springforbeginners.model.Customer
customerdispatcher-servlet.xml
<context:annotation-config />
<context:component-scan base-package="com.springforbeginners" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="loadTimeWeaver" ref="loadTimeWeaver" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
</bean>
<bean id="loadTimeWeaver" class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" >
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:jboss/TransactionManager"/>
<property name="userTransactionName" value="java:jboss/UserTransaction"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
CustomerServiceImpl.java
package com.springforbeginners.service;
import com.springforbeginners.dao.CustomerDAO;
import com.springforbeginners.model.Customer;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
public class CustomerServiceImpl implements CustomerService {
#Autowired
private CustomerDAO customerDAO;
#Transactional
#Override
public void addCustomer(Customer customer) {
customerDAO.addCustomer(customer);
}
#Transactional
#Override
public List<Customer> listCustomer() {
return customerDAO.listCustomer();
}
#Transactional
#Override
public void removeCustomer(Integer customerId) {
customerDAO.removeCustomer(customerId);
}
}
CustomerDAOImpl.java
package com.springforbeginners.dao;
import com.springforbeginners.model.Customer;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
#Repository
public class CustomerDAOImpl implements CustomerDAO {
#PersistenceContext(unitName="CustomerDetailsPU3")
private EntityManager entityManager;
#Override
public void addCustomer(Customer customer) {
entityManager.persist(customer);
}
#Override
public List<Customer> listCustomer() {
return entityManager.createQuery("select c from Customer c", Customer.class).getResultList();
}
#Override
public void removeCustomer(Integer customerId) {
Customer customer = (Customer) entityManager.getReference(Customer.class, customerId);
if (null != customer) {
entityManager.remove(customer);
}
}
}
I do not know what and where exactly is something missing. But with the above code the read operations are working as expected. Problem is with save operations. I have converted the above example to use non-JTA datasource(also modified standalone.xml for jta=false) and to use JpaTransactionManager as below
With non-JTA datasource and 'org.springframework.orm.jpa.JpaTransactionManager' all operations(read as well as save/update/delete) are working fine.
But the JTA version of my example is not working as expected(save operations not committing work to database). Any help/pointers appreciated.
Thanks
Prakash
James,
I will be running this application on JBoss. But one datasource on JBoss and other on Glassfish and transaction should span save operation on both datasources simultaneously. This is what I am trying to achieve. I have a web application including spring for service(data) layer currently running on JBoss.
As you said earlier - I will have two persistence.xmls one for JBoss and one for Glassfish. As I am doing this first time I was/am in doubt whether the transaction(that spans two datasources on different servers-in this case JBoss and Glassfish), can this be executed entirely by JBoss(in case if the entire business logic resides in serviceImpl class deployed on JBoss)? In this case I will be using JBoss transaction manager( property name="transactionManagerName" value="java:jboss/TransactionManager" ). Is this sufficient or do I need to similarly have Glassfish transaction manager too? Sorry if this has created the confusion.
Another question from me was that is there a provision for speifying jndi ports in persistence.xml/anywhere else?(Definitely I will have two different persistence.xmls and I will mention the target server as JBoss in one and as Glassfish in another).
Do we have a technique in spring by which business logic can be distributed across different servers like JBoss/Glassfish and still under one single transatcion? I did not know if this can be an option. Were u talking about this scenario in which it will require two different deployment scripts one for each server?
Thanks
Prakash
What is your persistence.xml?
Since you are using JTA, you must define the "eclipselink.target-server"="JBoss"
My persistence.xml(modified) now looks like below. Added target server property in persistence.xml. This solved the problem.
<persistence-unit name="CustomerDetailsPU3" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/mysql_customerdb3</jta-data-source>
<class>com.springforbeginners.model.Customer</class>
<properties>
<property name="eclipselink.target-server" value="JBoss" />
</properties>
</persistence-unit>
Thanks
Prakash

How to set up Spring Security SecurityContextHolder strategy?

I'm using asynchronous methods in my service (Spring 3 #Async annotation). And I've got a problem - spawned thread doesn't have security context. Cause of it is Spring Security by default uses SecurityContextHolder.MODE_THREADLOCAL strategy for its context holder. But I need to use SecurityContextHolder.MODE_INHERITABLETHREADLOCAL strategy.
For the moment I set up strategy in my AuthenticationSuccessHandler. But in my point of view it's not a good practice.
So how can I set it up in context configuration file?
Version of spring security is 3.0.0.
You can set the environment variable spring.security.strategy to MODE_INHERITABLETHREADLOCAL. You could also have a simple bean that during your web applications startup calls SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL) and initialize that value in your context configuration file.
SecurityContextHolder API
The java config for #viator 's answer if it helps you.
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}
A little bit another solution, like #viator write:
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder" />
<property name="targetMethod" value="setStrategyName" />
<property name="arguments" value="MODE_INHERITABLETHREADLOCAL" />
</bean>
Working like a charm.
Via Java configuration without reflection.
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.context.SecurityContextHolder;
#Configuration
public class SecurityConfig {
#PostConstruct
public void enableAuthCtxOnSpawnedThreads() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
}

Resources