Spring Injection of Data using Hibernate - spring

On initialisation of the web app, I am trying to inject some static data from the DB into the bean.
<bean id="CustomDriven" class="java.util.ArrayList">
<constructor-arg>
<value>#{FormCodeHibernateDAO.findAll()}</value>
</constructor-arg>
</bean>
I get an error
6:48:07,977 INFO [main] [UpdateTimestampsCache] starting update timestamps cache at region: org.hibernate.cache.UpdateTimestampsCache
16:48:07,981 INFO [main] [StandardQueryCache] starting query cache at region: org.hibernate.cache.StandardQueryCache
16:48:09,016 DEBUG [main] [GenericDaoJpa] findAll()
16:48:09,017 DEBUG [main] [GenericDaoJpa] getting HIBERNATE session...
16:48:09,196 ERROR [main] [GenericDaoJpa] Error when finding all
org.hibernate.SessionException: Session is closed!
at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
at org.hibernate.impl.SessionImpl.setFlushMode(SessionImpl.java:1433)
Any reason why I am getting this?

maybe the execution of #{FormCodeHibernateDAO.findAll()} is before than the application context start connection to database, i think so.

I figured the problem, my CustomDriven bean was talking to the DAO Impl directly.
I changed it to talk to the DAO using a service and the new configuration looks like
<bean id="CustomDriven" class="java.util.ArrayList">
<constructor-arg>
<value>#{dataDrivenService.getDataList()}</value>
</constructor-arg>
</bean>
And the DataDriverService class is
public interface DataDrivenService<T> {
public List<T> getDataList();
}
And the ServiceImpl is
#Service( value = "dataDrivenService" )
public class DataDrivenServiceImpl implements DataDrivenService {
#Autowired
#Qualifier( value = "formCodeDAO" )
private FormCodeDAO dao;
#Override
#Transactional( readOnly = true )
public List<FormCode> getDataList() {
return dao.findAll();
}
}
Where FormCodeDAO in interface that extends the GenericDAO implementation

Related

406 error on Spring MVC integration test, while the service works fine in browser

I have a Spring 4 MVC web application. I am doing the Integration Test for my REST Services. The services are working fine from invoking through browser rest-clients and jquery/restangular UI as well. However, when I run my Integration Test, I am getting the error Expected :200 Actual :406.
This issue comes only when Spring convert the Object to json. I tried manual conversion by ObjectMapper and returned the result. In this case, the test started working.
Here are my files:
Controller:
#RequestMapping(value="/permissions", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Object> getPermissions() throws Exception {
return new ResponseEntity<Object>(getPermissions(), HttpStatus.OK);
}
Integration Test:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({"classpath*:rest-config.xml", "classpath:domain-config.xml"})
public class ITController {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void getPermissions() throws Exception {
MvcResult result = this.mockMvc.perform(get("/permissions/4")
.accept("application/json"))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json")).andReturn();
Permission p = new GsonBuilder().create().fromJson(result.getResponse().getContentAsString(), Permission.class);
Assert.assertNotNull(p);
}
}
If I add the below code to the controller, then the test start working.
ObjectMapper mapper = new ObjectMapper();
String stringVal = mapper.writeValueAsString(permission);
Part of my spring config file:
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="order" value="1"/>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/plain;charset=UTF-8"/>
</bean>
</list>
</property>
</bean>
I am using jackson version 2.2.1 in my application.
DEBUG Log
2014-07-14 14:41:37 DEBUG EntityPrinter:121 - com.myapp.entity.Permission{isActive=true, description=permission, id=4, Name=mypermission}
2014-07-14 14:41:37 DEBUG JdbcTransaction:113 - committed JDBC Connection
2014-07-14 14:41:37 DEBUG JdbcTransaction:126 - re-enabling autocommit
2014-07-14 14:41:37 DEBUG LogicalConnectionImpl:314 - Releasing JDBC connection
2014-07-14 14:41:37 DEBUG LogicalConnectionImpl:332 - Released JDBC connection
2014-07-14 14:41:37 DEBUG ConnectionProxyHandler:219 - HHH000163: Logical connection releasing its physical connection

Accessing a Spring Bean from a Servlet

I have a Spring Bean defined in my applicationContext like:
<bean id="spaceReader" class="com.company.SpaceReader">
</bean>
I would like to be able to access this bean in my Application Servlet without having to use:
ApplicationContext context = new ClassPathXmlApplicationContext(CONTEXT_LOCATION);
context.getBean("SpaceReader");
I've tried exporting it using the following:
<bean id="ContextExporter" class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="contextExporterAttributes">
<map>
<entry key="SpaceReaderKey">
<ref local="spaceReader" />
</entry>
</map>
</property>
</bean>
but when i inject it into the Servlet, it returns a Null value. Just wondering if there's something i'm missing when i export the Bean or when i try to access it in the Servlet?
You can inject dependencies using annotations even in servlet (there is a special SpringBeanAutowiringSupport helper class for this pourpose):
public class CustomServlet extends HttpServlet {
#Autowired
private ProductService productService;
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// inject productService dependency
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
....
}

How to execute SQL script only once at startup in Spring?

I have a web application based on Spring JDBC and Jersey RESTful web service. I'm using the following Spring JDBC template class to initiate the dataSource and execute an SQL script (update_condition_table.sql):
public class CustomerJDBCTemplate implements CustomerDAO {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
Resource rc = new ClassPathResource("update_condition_table.sql");
JdbcTestUtils.executeSqlScript(jdbcTemplateObject, rc, false);
}
// ......other methods
}
The bean configuration file is beans.xml:
<!-- Initialization for data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/customer" />
<property name="username" value="root" />
<property name="password" value="mypassword" />
</bean>
<!-- Definition for customerJDBCTemplate bean -->
<bean id="customerJDBCTemplate" class="com.example.db.CustomerJDBCTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
The Jersey controller class contains the instantiation of class CustomerJDBCTemplate and serves as the REST web service:
#Path("/customer")
public class CustomerService {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
CustomerJDBCTemplate dbController = (CustomerJDBCTemplate) context.getBean("customerJDBCTemplate");
// ... some GET/POST methods
}
When I launched my web app by entering the index URL in the browser, the SQL script gets executed by the customerJDBCTemplate bean. However, when I clicked to navigate to other pages, it crashed and reported that the SQL script cannot be executed again. So obviously the SQL script was executed again after initialization of dataSource and initial launch of the index web page. How to avoid this by just running the SQL script only once upon initial startup of the web app?
Looks like I need to move the bean instantiate code out of CustomerService class, but where should I put that code?
I figured it out that I should set the bean application context to be static within CustomerService class and do it in the static initialization block as follows:
#Path("/customer")
public class CustomerService {
private static ApplicationContext context;
private static CustomerJDBCTemplate dbController;
static {
context = new ClassPathXmlApplicationContext("beans.xml");
dbController = (CustomerJDBCTemplate) context.getBean("customerJDBCTemplate");
}
//... other methods
}
I guess the reason is Jersey creates a different instance of CustomerService for each HTTP session (correct me if I'm wrong). So if I set the bean context as instance variable, it will do the initialization for every HTTP request.
Have your CustomerJDBCTemplate implement InitializingBean. afterPropertiesSet will get called once, right after all properties have been set by Spring's BeanFactory.
For example:
public class CustomerJDBCTemplate implements CustomerDAO, InitializingBean {
...
// ......other methods
public void afterPropertiesSet() throws Exception {
//do your initializing, or call your initializing methods
}
}

How to store static field?

In a redis java client,I found this:
To use it, init a pool:
JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
You can store the pool somewhere statically, it is thread-safe.
I just wondering,with spring,how can I store JedisPool statically.
You don't.
In spring it's preferable to define a JedisPool bean and autowire it wherever necessary.
For example, using xml config:
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg>
<bean class="redis.clients.jedis.JedisPoolConfig" />
</consrtuctor-arg>
<constructor-arg value="localhost" />
</bean>
and then, inside your beans:
#Autowire
JedisPool jedisPool;
It's even simpler if you use spring java config - you can use exactly the code you posted to define the pool bean:
#Configuration
public class Configuration {
#Bean
public JedisPool createJedisPool() {
return new JedisPool(new JedisPoolConfig(), "localhost");
}
}
Also you might want to take a look at spring-data - redis

Spring setting WebApplicationContext in ServletContextAware bean

I'm converting existing code to Spring 3 JDBC. I've put it into a class (SpringDB.Users) that implements ServletContextAware. In setServletContext(), the following code doesn't work:
public void setServletContext(ServletContext sc)
{
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
simpleJdbcTemplate = (SimpleJdbcTemplate) wac.getBean("simpleJdbcTemplate");
}
The reason is: exception is java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
However I did register a ContextLoaderListener in web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
The applicationContext.xml has this:
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/mysql"/>
<bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg>
<ref bean="dataSource"/>
</constructor-arg>
</bean>
<bean class="SpringDB.Users"/>
which results in getting the call to setServletContext(). The class SpringDB.Users is mostly static stuff. It is never instantiated by the java code.
Apparently, the call to WebApplicationContextUtils.getRequiredWebApplicationContext() is "too early". Because what does work without any trouble is to get the WebApplicationContext at a later time, i.e. when database work really starts - so what I do is to call a private function getSimpleJdbcTemplate() instead of a private variable simpleJdbcTemplate:
static private SimpleJdbcTemplate getSimpleJdbcTemplate ()
{
if (simpleJdbcTemplate == null)
{
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
simpleJdbcTemplate = (SimpleJdbcTemplate) wac.getBean("simpleJdbcTemplate");
}
return simpleJdbcTemplate;
}
Is there any solution so that the variable simpleJdbcTemplate can be initialized within setServletContext() ?
Am I missing something obvious, or just expecting too much?
Why do you need that in the first place?
If your class is a bean, then you can simply inject (with #Inject, #Autowired or xml) the jdbc template:
#Inject
private SimpleJdbcTemplate template;

Resources