How to perform Hsqldb SET Operation dynamically in Spring - spring

We are using HSQL Database Engine 2.3.2 with Spring 4.1.0.RELEASE while my spring configuration is as following:
Here is applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" 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-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
<bean class="com.chorke.spring.bootstarp.HyperSqlDbServer" id="hsqldb" init-method="start">
<constructor-arg>
<props>
<prop key="server.port">9002</prop>
<prop key="server.dbname.0">chorke</prop>
<prop key="server.remote_open">true</prop>
<prop key="server.database.0">file:~/.hsqldb/chorke/data;sql.syntax_mys=true;user=admin;password=pa55word</prop>
<prop key="hsqldb.default_table_type">text</prop>
<prop key="hsqldb.reconfig_logging">false</prop>
</props>
</constructor-arg>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbc.JDBCDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost:9002/chorke" />
<property name="username" value="admin" />
<property name="password" value="pa55word" />
</bean>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="classpath:schema.sql"/>
<jdbc:script location="classpath:data.sql"/>
</jdbc:initialize-database>
</beans>
Here is com.chorke.spring.bootstarp.HyperSqlDbServer
package com.chorke.spring.bootstarp;
import java.io.IOException;
import java.util.Properties;
import org.hsqldb.Server;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.server.ServerAcl.AclFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;
public class HyperSqlDbServer implements SmartLifecycle {
private final Logger logger = LoggerFactory.getLogger(HyperSqlDbServer.class);
private HsqlProperties properties;
private Server server;
private boolean running = false;
public HyperSqlDbServer(Properties props) {
properties = new HsqlProperties(props);
}
#Override
public boolean isRunning() {
if (server != null)
server.checkRunning(running);
return running;
}
#Override
public void start() {
if (server == null) {
logger.info("Starting HSQL server...");
server = new Server();
try {
server.setProperties(properties);
server.start();
running = true;
} catch (AclFormatException afe) {
logger.error("Error starting HSQL server.", afe);
} catch (IOException e) {
logger.error("Error starting HSQL server.", e);
}
}
}
#Override
public void stop() {
logger.info("Stopping HSQL server...");
if (server != null) {
server.stop();
running = false;
}
}
#Override
public int getPhase() {
return 0;
}
#Override
public boolean isAutoStartup() {
return true;
}
#Override
public void stop(Runnable runnable) {
stop();
runnable.run();
}
}
Here is schema.sql
CREATE TABLE IF NOT EXISTS t001i001(pf_id INTEGER,df_name VARCHAR(20));
--SET TABLE t001i001 SOURCE 't001i001.csv;fs=|;vs=.';
Here is data.sql
insert into t001i001(pf_id, df_name) values(1, 'Shefat Hossain');
Where I want to add some script to perform some SET operation dynamically as like as what was commented in schema.sql on second line. using spring.
Any way to perform SET operation logically/dynamically inside Spring Application Context?

Here is wrong assumption of me as As I declared the property at applicationContext.xml on hsqldb bean as below:
<prop key="hsqldb.default_table_type">text</prop>
It's suppose to me that it would be help us to defaulting database table engine TEXT instead of MEMORY. As the table default engine was MEMORY so the 2nd line of schema.sql not executing. after editing schema.sql it working fine, no problem on SET operation as following:
CREATE TEXT TABLE IF NOT EXISTS t001i001(pf_id INTEGER,df_name VARCHAR(20));
SET TABLE t001i001 SOURCE 't001i001.csv;fs=|;vs=.';

Related

How to access openshift contained hsqldb server port publicly?

We are using HSQL Database Engine 2.3.2 with Spring 4.2.0.RELEASE while my spring configuration is as following:
Here is applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" 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-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<bean class="com.chorke.spring.bootstarp.HyperSqlDbServer" id="hsqldb" init-method="start">
<constructor-arg>
<props>
<prop key="server.port">55511</prop>
<prop key="server.dbname.0">chorke</prop>
<prop key="server.remote_open">true</prop>
<prop key="server.database.0">file:~/.hsqldb/chorke/data;sql.syntax_mys=true;user=admin;password=pa55word</prop>
<prop key="hsqldb.default_table_type">text</prop>
<prop key="hsqldb.reconfig_logging">false</prop>
</props>
</constructor-arg>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbc.JDBCDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost:55511/chorke" />
<property name="username" value="admin" />
<property name="password" value="pa55word" />
</bean>
</beans>
Here is com.chorke.spring.bootstarp.HyperSqlDbServer
package com.chorke.spring.bootstarp;
import java.io.IOException;
import java.util.Properties;
import org.hsqldb.Server;
import org.hsqldb.persist.HsqlProperties;
import org.hsqldb.server.ServerAcl.AclFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;
public class HyperSqlDbServer implements SmartLifecycle {
private final Logger logger = LoggerFactory.getLogger(HyperSqlDbServer.class);
private HsqlProperties properties;
private Server server;
private boolean running = false;
public HyperSqlDbServer(Properties props) {
properties = new HsqlProperties(props);
}
#Override
public boolean isRunning() {
if (server != null)
server.checkRunning(running);
return running;
}
#Override
public void start() {
if (server == null) {
logger.info("Starting HSQL server...");
server = new Server();
try {
server.setProperties(properties);
server.start();
running = true;
} catch (AclFormatException afe) {
logger.error("Error starting HSQL server.", afe);
} catch (IOException e) {
logger.error("Error starting HSQL server.", e);
}
}
}
#Override
public void stop() {
logger.info("Stopping HSQL server...");
if (server != null) {
server.stop();
running = false;
}
}
#Override
public int getPhase() {
return 0;
}
#Override
public boolean isAutoStartup() {
return true;
}
#Override
public void stop(Runnable runnable) {
stop();
runnable.run();
}
}
Edited:
As the following code snippet we are able to start hsqldb server on port 55511 in my local PC. But unable to start using Openshift JBoss EWS 2.0 inside spring context. Where there is an error occurred as following:
[Server#15a1792]: Initiating startup sequence...
[Server#15a1792]: [Thread[HSQLDB Server #15a1792,5,main]]: run()/openServerSocket():
java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
at java.net.ServerSocket.bind(ServerSocket.java:376)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at org.hsqldb.server.HsqlSocketFactory.createServerSocket(Unknown Source)
at org.hsqldb.server.Server.openServerSocket(Unknown Source)
at org.hsqldb.server.Server.run(Unknown Source)
at org.hsqldb.server.Server.access$000(Unknown Source)
at org.hsqldb.server.Server$ServerThread.run(Unknown Source)
[Server#15a1792]: Initiating shutdown sequence...
[Server#15a1792]: Shutdown sequence completed in 4 ms.
[Server#15a1792]: 2016-03-23 23:41:21.881 SHUTDOWN : System.exit() was not called
Regarding this issue my questionnaires are as following:
How to achieve permission to open an custom server port Like hsqldb, h2db, MLLP, ActiveMQ, HornetQ?
Do we need extra configuration to access custom server port if we are able to open an custom server port?
If there is an configuration required, would you please provide us any guide line regarding this issue?
Finally I beg your help to open an custom server port Like hsqldb, h2db, MLLP, ActiveMQ, HornetQ and access it publicly from Openshift Gear/Cartridge.

spring, hibernate, postgres database query

I have a problem with my spring, hibernate app. I'm trying to make a login with spring security and im having little trouble geting my user account query to DB to work.
Problem is that my code will reach "test1" but it won't reach "test2" and since I'm not getting any errors to console and also app will continue running I have no clue what the problem might be.
When I press "login" button, I will directed to login failed page. Also I'll point out that I am new with spring and hibernate.
Anybody have any ideas what I'm doing wrong?
UserAccountService.java
package main.java.services;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import main.java.model.UserAccount;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service("userAccountService")
#Transactional
public class UserAccountService {
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager){
this. entityManager = entityManager;
}
public UserAccount get(Integer id)
{
Query query = entityManager.createQuery("FROM user_account as ua WHERE ua.id="+id);
return (UserAccount) query.getSingleResult();
}
public UserAccount get(String username)
{
System.out.println("test1");
Query query = entityManager.createQuery("FROM user_account as ua WHERE ua.username='"+username+"'");
System.out.println("test2");
return (UserAccount) query.getSingleResult();
}
public void add(UserAccount userAccount)
{
entityManager.persist(userAccount);
}
}
LoginService.java
package main.java.services;
import javax.annotation.Resource;
import main.java.model.UserAccount;
import main.java.security.CustomUserDetails;
import main.java.security.UserGrantedAuthority;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
public class LoginService implements UserDetailsService{
#Resource(name="userAccountService")
private UserAccountService userAccountService;
public LoginService(){ }
public UserDetails loadUserByUsername(String username){
if (username != null && !username.equals("")){
UserAccount userAccount = userAccountService.get(username);
System.out.println(userAccount);
if (userAccount == null) {
return null;
}
GrantedAuthority grantedAuth = new UserGrantedAuthority(userAccount.getAuthority());
System.out.println(userAccount.getId() + userAccount.getAuthority()+userAccount.getPassword());
return new CustomUserDetails(userAccount.getId(), userAccount.getUsername(), userAccount.getPassword(), new GrantedAuthority[]{ grantedAuth });
} else {
return null;
}
}
}
hibernateContext.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:property-placeholder location="/WEB-INF/jdbc.properties" />
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${jdbc.driverClassName}"
p:jdbcUrl="${jdbc.url}"
p:user="${jdbc.username}"
p:password="${jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" />
<!-- Declare a JPA entityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
<property name="persistenceUnitName" value="hibernatePersistenceUnit" />
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
<property name="databasePlatform">
<value>${jdbc.dialect}</value>
</property>
<property name="showSql" value="true"/>
</bean>
</property>
</bean>
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
For the first time of reading your post I can detect that your query is wrong...
Your query is an sql query. In this case you should use createNativeQuery()
instead of createQuery(). The proper query is (assuming that I do not know
you classes):
Query query = entityManager.createQuery("SELECT us FROM UserAccount as ua WHERE ua.username='"+username+"'");
where UserAccount is the name of the class, not the name of the table. Moreover
it is better using a prepared statement (google it) for passing arguments to the query.

Specify a custom web.xml to an embedded tomcat

Is there a way to specify a different web.xml from the standard WEB-INF/web.xml when using an embedded tomcat instance?
I would like to put a web.xml in my src/test/resources (or some other area) and refer to that web.xml when starting the embedded tomcat.
Here is my existing code to start the tomcat instance
tomcat = new Tomcat();
String baseDir = ".";
tomcat.setPort(8080);
tomcat.setBaseDir(baseDir);
tomcat.getHost().setAppBase(baseDir);
tomcat.getHost().setAutoDeploy(true);
tomcat.enableNaming();
Context ctx = tomcat.addWebApp(tomcat.getHost(), "/sandbox-web", "src\\main\\webapp");
File configFile = new File("src\\main\\webapp\\META-INF\\context.xml");
ctx.setConfigFile(configFile.toURI().toURL());
tomcat.start();
I am starting this server from a tomcat instance and I would like to do the following when running unit tests
turn off the contextConfigLocation
specify a custom ContextLoaderListener that sets the parent ApplicationContext of the embedded tomcat.
This file might be specified like so:
File webXmlFile = new File("src\\test\\resources\\embedded-web.xml");
Edit
After much frustration I realized that no matter what I do, I cannot persuade tomcat from looking in WEB-INF for web.xml. It appears that I must ignore the web.xml altogether and set the items in the web.xml programmatically.
I ended up with this configuration:
cucumber.xml for configuring tests
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="applicationContextProvider" class="ca.statcan.icos.sandbox.ApplicationContextProvider"/>
<bean id="sandBoxDataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:testdb;shutdown=true;" />
<property name="username" value="SA" />
<property name="password" value="" />
</bean>
<!-- Support for JPA related annotation support (#PersistenceUnit and #PersistenceContext) -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- JTA Configuration -->
<bean id="jtaTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown"><value>true</value></property>
</bean>
<bean id="jtaUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" />
<bean id="springTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="userTransaction" ref="jtaUserTransaction" />
</bean>
<!-- JPA Entity Manager configuration -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
lazy-init="true">
<property name="persistenceUnitName" value="sandBox" />
<property name="dataSource" ref="sandBoxDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="SQL_SERVER" />
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
<property name="jpaPropertyMap">
<props>
<prop key="hibernate.archive.autodetection">class</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<!-- Second Level Cache : EHCache in dev
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop> -->
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<import resource="classpath:META-INF/applicationContext-core.xml" />
<import resource="classpath:META-INF/applicationContext-web.xml" />
</beans>
applicationContext-core.xml - where the services are configured
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd"
default-autowire="byName">
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath*:META-INF/fms-local.properties" />
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
</bean>
<!--
Classpath scanning to load all the service classes
-->
<context:component-scan base-package="ca.statcan"
use-default-filters="false">
<context:include-filter type="regex" expression="ca\.statcan\.icos.*\.service\..*Service" />
<context:include-filter type="regex" expression="ca\.statcan\.icos.*\.builders\..*Builder" />
</context:component-scan>
<!--
Spring TransactionManager
-->
<tx:advice id="txAdvice" transaction-manager="springTransactionManager">
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" propagation="SUPPORTS" isolation="DEFAULT"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS" isolation="DEFAULT"/>
<!-- other methods use the default transaction settings -->
<tx:method name="*" read-only="false" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!--
AOP Weaving for all Service methods
-->
<aop:config proxy-target-class="true">
<aop:pointcut id="icosServiceMethods" expression="execution(* ca.statcan.icos..*.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="icosServiceMethods" />
</aop:config>
</beans>
Custom ContextLoaderListener
public class EmbeddedContextLoaderListener extends ContextLoaderListener {
#Override
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
GenericWebApplicationContext context = new GenericWebApplicationContext(sc);
context.setParent(ApplicationContextProvider.getApplicationContext());
return context;
}
#Override
protected ApplicationContext loadParentContext(ServletContext servletContext) {
return ApplicationContextProvider.getApplicationContext();
}
}
Modified Embedded Tomcat Wrapper
public class EmbeddedTomcat {
/** Log4j logger for this class. */
#SuppressWarnings("unused")
private static final Logger LOG = LoggerFactory.getLogger(EmbeddedTomcat.class);
private Tomcat tomcat;
public void start() {
try {
tomcat = new Tomcat();
String baseDir = ".";
tomcat.setPort(8080);
tomcat.setBaseDir(baseDir);
tomcat.getHost().setAppBase(baseDir);
tomcat.getHost().setDeployOnStartup(true);
tomcat.getHost().setAutoDeploy(true);
tomcat.enableNaming();
Context context = tomcat.addContext("/sandbox-web", "src\\main\\webapp");
Tomcat.initWebappDefaults(context);
configureSimulatedWebXml(context);
LOG.info("Starting tomcat in: " + new File(tomcat.getHost().getAppBase()).getAbsolutePath());
tomcat.start();
} catch (LifecycleException e) {
throw new RuntimeException(e);
}
}
public void stop() {
try {
tomcat.stop();
tomcat.destroy();
FileUtils.deleteDirectory(new File("work"));
FileUtils.deleteDirectory(new File("tomcat.8080"));
} catch (LifecycleException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void deploy(String appName) {
tomcat.addWebapp(tomcat.getHost(), "/" + appName, "src\\main\\webapp");
}
public String getApplicationUrl(String appName) {
return String.format("http://%s:%d/%s", tomcat.getHost().getName(),
tomcat.getConnector().getLocalPort(), appName);
}
public boolean isRunning() {
return tomcat != null;
}
private void configureSimulatedWebXml(final Context context) {
// Programmatically configure the web.xml here
context.setDisplayName("Sandbox Web Application");
context.addParameter("org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG", "/WEB-INF/tiles-defs.xml,/WEB-INF/tiles-sandbox.xml");
final FilterDef struts2Filter = new FilterDef();
struts2Filter.setFilterName("struts2");
struts2Filter.setFilterClass("org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter");
struts2Filter.addInitParameter("actionPackages", "ca.statcan.icos.sandbox.web");
context.addFilterDef(struts2Filter);
final FilterMap struts2FilterMapping = new FilterMap();
struts2FilterMapping.setFilterName("struts2");
struts2FilterMapping.addURLPattern("/*");
context.addFilterMap(struts2FilterMapping);
context.addApplicationListener("org.apache.tiles.web.startup.TilesListener");
context.addApplicationListener("ca.statcan.icos.sandbox.EmbeddedContextLoaderListener");
context.addWelcomeFile("index.jsp");
}
}
Step definitions
public class StepDefs {
#Autowired
protected EmployeeEntityService employeeEntityService;
#Given("^the following divisions exist$")
public void the_following_divisions_exist(DataTable arg1) throws Throwable {
final Employee employee = new Employee(3, "Third", "John", null, "613-222-2223");
employeeEntityService.persistEmployee(employee);
}
#Given("^there are no existing surveys$")
public void there_are_no_existing_surveys() throws Throwable {
}
#When("^I register a new survey with the following information$")
public void I_register_a_new_survey_with_the_following_information(DataTable arg1) throws Throwable {
Capabilities capabilities = DesiredCapabilities.htmlUnit();
final HtmlUnitDriver driver = new HtmlUnitDriver(capabilities);
driver.get("http://localhost:8080/sandbox-web/myFirst");
}
#Then("^the surveys are created$")
public void the_surveys_are_created() throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
#Then("^a confirmation message is displayed saying: \"([^\"]*)\"$")
public void a_confirmation_message_is_displayed_saying(String arg1) throws Throwable {
// Express the Regexp above with the code you wish you had
throw new PendingException();
}
}
Action class
#Results({ #Result(name = "success", location = "myFirst.page", type = "tiles") })
#ParentPackage("default")
#Breadcrumb(labelKey = "ca.statcan.icos.sandbox.firstAction")
#SuppressWarnings("serial")
public class MyFirstAction extends HappyfActionSupport {
private List<Employee> employees;
#Autowired
private EmployeeEntityService employeeEntityService;
#Override
public String execute() {
employees = employeeEntityService.getAllEmployee();
if (employees.size() == 0) {
// persist data in memory
final Employee employee1 = new Employee(1, "First", "John", null, "613-222-2222");
employeeEntityService.persistEmployee(employee1);
final Employee employee2 = new Employee(2, "Second", "John", null, "613-222-2223");
employeeEntityService.persistEmployee(employee2);
employees = employeeEntityService.getAllEmployee();
}
return SUCCESS;
}
public List<Employee> getEmployees() {
return employees;
}
}
With this, the embedded tomcat starts correctly and all seems to go well until I try to navigate to a web page. In the StepDefs class, the EmployeeEntityService is injected correctly. However, in the Action class, EmployeeEntityservice is not injected (it remains null).
According to my knowledge, I am setting the parent ApplicationContext for the embedded Tomcat correctly. So why isn't the server using the parent context to get the EmployeeEntityService?
I was stuck with a similar problem and the solution for using an alternative web.xml is simpler than one would dare to think:
2 lines:
Context webContext = tomcat.addWebapp("/yourContextPath", "/web/app/docroot/");
webContext.getServletContext().setAttribute(Globals.ALT_DD_ATTR, "/path/to/custom/web.xml");
Voila! The magic happens in org.apache.catalina.startup.ContextConfig#getWebXmlSource
Disclaimer: Tested on Tomcat 7.0.42

How to get spring configuration from database

I'm using Eclipse Juno, JDK 7, tomcat 7.0.29, hibernate 4.1.5 and Spring 3.1.2.
I'm trying to load Spring configuration info from database. This is what I could do until now:
WEB.XML
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/context-beans.xml
</param-value>
</context-param>
jdbc.properties
jdbc.driver_class=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://localhost;databaseName=mydbname;
jdbc.username=<my_usr>
jdbc.password=<my_pwd>
context-beans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd">
<!-- Configure which package will contain our components -->
<context:component-scan base-package="com.xxx" />
<context:annotation-config />
<mvc:annotation-driven />
<mvc:resources mapping="/static/**" location="/static/" />
<tx:annotation-driven />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="appPersistenceUnit" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
p:url="jdbc:sqlserver://localhost;databaseName=appDB" p:username="theUserName" p:password="thePassword" destroy-method="close"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" lazy-init="false" >
<property name="dataSource" ref="dataSource" />
<property name="lazyInit" value="false" />
</bean>
<bean id="appProperties" class="com.xxx.web.util.MyAppPropertyPlaceholderConfigurer">
<property name="nameColumn" value="key" />
<property name="valueColumn" value="value" />
<property name="tableName" value="app_params" />
<property name="whereClause" value="param_type = 'GLOBAL'" />
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- Files path configuration -->
<mvc:resources mapping="/iconfiles/**" location="file:/${PATH.ICON_FILES}" />
</beans>
Please consider table app_params contains 1 record where key="PATH.ICON_FILES", value="c:/temp/icons/" and param_type="GLOBAL".
MyAppPropertyPlaceholderConfigurer
package com.xxx.web.util;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
public class MyAppPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private JdbcTemplate jdbcTemplate;
private String nameColumn;
private String valueColumn;
private String tableName;
private String whereClause;
public MyAppPropertyPlaceholderConfigurer() {
super();
setPlaceholderPrefix("${");
}
#Override
protected void loadProperties(final Properties props) throws IOException {
if (null == props) {
throw new IOException("No properties passed by Spring framework - cannot proceed.");
}
String sql = String.format("SELECT [%s], [%s] FROM [%s] %s", nameColumn, valueColumn, tableName, whereClause);
logger.info("Reading configuration properties from database. Query=" + sql);
try {
jdbcTemplate.query(sql, new RowCallbackHandler() {
#Override
public void processRow(ResultSet rs) throws SQLException {
String name = rs.getString(nameColumn);
String value = rs.getString(valueColumn);
if (null == name || null == value) {
throw new SQLException("Configuration database contains empty data. Name='" + (name == null ? "" : name)
+ "', Value='" + (value == null ? "" : value) + "'.");
}
props.setProperty(name, value);
}
});
} catch (Exception e) {
logger.fatal("There is an error in either 'application.properties' or the configuration database.");
throw new IOException(e);
}
if (props.size() == 0) {
logger.fatal("The configuration database could not be reached or does not contain any properties in '" + tableName
+ "'.");
} else {
logger.info("Application config info loaded from configuration database.");
}
}
#Override
protected String convertPropertyValue(String originalValue) {
if (originalValue.startsWith("!!")) {
// TODO ex: return EncryptUtil.decrypt(originalValue); see org.owasp.esapi.reference.crypto.EncryptedPropertiesUtils
return originalValue;
}
return originalValue;
}
public void setJdbcTemplate(JdbcTemplate newJdbcTemplate) {
this.jdbcTemplate = newJdbcTemplate;
}
public void setNameColumn(String newNameColumn) {
this.nameColumn = newNameColumn;
}
public void setValueColumn(String newValueColumn) {
this.valueColumn = newValueColumn;
}
public void setTableName(String newTableName) {
this.tableName = newTableName;
}
public void setWhereClause(String newWhereClause) {
if (newWhereClause == null || newWhereClause.trim().length() == 0) {
this.whereClause = "";
} else {
if (newWhereClause.trim().toUpperCase().startsWith("WHERE ")) {
this.whereClause = newWhereClause;
} else {
this.whereClause = "WHERE " + newWhereClause;
}
}
}
}
Doing it this way works as expected and I have variable ${PATH.ICON_FILES} properly resolved.
However, I don't want to have my dataSource bean with username, password and all stuff hard coded on the XML file. I would like to load it from another property file, preferentially encrypted.
How do I get this done?
I already tried to add another PropertyPlaceholderConfigurer with jdbc configuration (plain text at this time) by adding the code below into context-beans.xml:
<bean id="jdbcConfigurer" name="jdbcConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
Then I changed dataSource bean to read from there:
<bean id="dataSource" name="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" p:driverClassName="${jdbc.driver_class}"
p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" destroy-method="close" />
When I try to run I get the following error:
[2012-10-10 11:33:48,744] WARN (SQLErrorCodesFactory.java:227) - Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driver_class}'
Any idea what I'm doing wrong here? Looks like it is instantiating MyAppPropertyPlaceholderConfigurer prior to getting the values from the regular PropertyPlaceholderConfigurer...
Thanks.

Injection of the sessionFactory not working

I'm new with Spring and I want to inject the sessionFactory and its not working at all. I'm starting a web server Jetty and then I load the context. After i start a GWT web application, I make a call on the server side and I try to get some info but I get a null pointer. There is no error at all so it make it difficult to know where the problem is. I know its suppose to work because I saw it working on a project I worked on some times ago. Any help will be appreciate. (Sorry for my possibly bad english)
Here is the context.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema
/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema
/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema
/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema
/security/spring-security-3.0.xsd">
<!-- Standard spring initialization -->
<context:component-scan base-package="com.test">
</context:component-scan>
<tx:annotation-driven transaction-manager="txManager"/>
<!-- Connection to the database-->
<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="123456789" />
</bean>
<!-- Hibernate session factory-->
<bean id="jpaSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.domain"/>
<property name="namingStrategy" >
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- Hibernate session factory -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="jpaSessionFactory" />
</bean>
</beans>
Here is the main :
public static void main(String[] args) {
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[]
{ new AppContextBuilder().buildWebAppContext()});
final JettyServer jettyServer = new JettyServer();
jettyServer.setHandler(contexts);
Runnable runner = new Runnable() {
#Override
public void run() {
new ServerRunner(jettyServer);
}
};
EventQueue.invokeLater(runner);
new ClassPathXmlApplicationContext("context.xml");
}
Here is the class Test where I want the injection :
#Component("test")
public class TEST{
#Resource(name="jpaSessionFactory")
private SessionFactory sessionFactory;
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<Personne> getPersonnes() {
Session s = sessionFactory.getCurrentSession();
Query query = s.createQuery("from Person");
return query.list();
}
}
Here is the server side from the application (not shown completely)
/*** The server side implementation of the RPC service.
*/
#SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
#Resource
private TEST t;
public String greetServer(String input) throws IllegalArgumentException {
// Verify that the input is valid.
if (!FieldVerifier.isValidName(input)) {
// If the input is not valid, throw an IllegalArgumentException
back to
// the client.
throw new IllegalArgumentException(
"Name must be at least 4 characters long");
}
t.getPersons(); // NULL pointer here
.........................
The MySQL tables are created like it should, so all the scanning seems to work.
Thanks
Bob
This is because the GreetingServiceImpl class is not created by spring - it is servlet that is initialized by the container directly. Follow the instructions in this article to fix the issue. I have copied the relevant code from the article.
#Override
public void init() throws ServletException {
super.init();
final WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
if (ctx == null) {
throw new IllegalStateException("No Spring web application context found");
}
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
}

Resources