0

I see so many questions on this and have tried numerous permutations of the many different solutions and none have worked.

I have a dao that requires a hibernate sessionfactory to do transactions. In the SpringMVC Context I've seen it working but the dao included in a java class is null. There is no error in catalina.out:

my full applicationContext.xml(because I really think the problem is here somewhere):

<?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:tx="http://www.springframework.org/schema/tx"
   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/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd">

<!-- Scan classpath for annotations (eg: @Service, @Repository etc)-->

<context:annotation-config/>

<context:component-scan base-package="com.shazam.di.*" />

<!-- JNDI Data Source. this works I can get to it independent of spring-->
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"
scope="singleton">
    <property name="jndiName" value="jdbc/dostudentdb"/>
    <property name="resourceRef" value="true"/>
</bean>

<tx:annotation-driven/>

<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan">
    <array>
        <value>com.shazam.di.spring.coursemgmt.dao</value>
    </array>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.show_sql">false</prop>
            <!--<prop key="hibernate.hbm2ddl.auto">update</prop>-->
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        </props>        
    </property>
</bean>

<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
</bean>

<!--I've alternated between contructor, properties for getters & setters --> 
<!--here, and nothing (just letting it get autowired into the private-->
<!--SessionFactory instance, no effing cigar!!-->
<bean id="studentDAO" class="org.shazam.di.spring.coursemgmt.dao.StudentDAO">
    <!--<constructor-arg type="SessionFactory" value="mySessionFactory"/>-->
    <property name="insertUserProfile" ref="insertUserProfile"/>
</bean>
</beans>

The class for which the DAO but not the sessionFactory can be found:

@Component
public class CheckClassAccess
{
    @Autowired 
    private static StudentDAO studentDAO;...

The beginning of the DAO(tried autwiring only getter & setters and a constructor):

@Repository
@SuppressWarnings({"unchecked", "rawtypes"})
public class StudentDAO {

    @Autowired 
    private SessionFactory sessionFactory;
etc...

The WEB XML Spring lines:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:WEB-INF/applicationContext.xml</param-value>
</context-param>    
and then a little later...
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> 

The only other caveat to this is that I'm attempting to get this to work within an opensource java cms called Opencms. But not sure that's relevant as the files that I'm wiring to are vanilla java support class, not controllers or anything(not really looking to do Spring-MVC with it just yet).

In fact all of this works in a Spring MVC servlet-context on a seperate smaller application but I just cannot seem to get these same objects/annotations to register in the applicationContext.

Marc Johnson
  • 75
  • 1
  • 12
  • What package is `StudentDAO` in? – Sotirios Delimanolis Sep 27 '13 at 19:04
  • How are you assessing CheckClassAccess object and were are these classes/ are these classes comes under sub package of com.shazam.di and also try removing .* in package scan – Karthik Prasad Sep 27 '13 at 19:16
  • StudentDAO is in com.shazam.di.spring.coursemgmt.dao – Marc Johnson Sep 27 '13 at 20:24
  • CheckClassAccess is at com.shazam.di.jsp.controllers.pages.support. I also noticed in the localhostddmmyyy.log that there is a line when tomcat is spinning up "INFO: No Spring WebApplicationInitializer types detected on classpath" that might mean something. – Marc Johnson Sep 27 '13 at 20:36
  • I removed the .* and restarted debugged the code in the try as soon as it gets to the line in my code "Student student = (Student)studentDAO.getStudent(sUsername)", it jumps to the catch with a nullpointer exception. I cannot even do a f5 while stepping through the code to get inside the object. – Marc Johnson Sep 27 '13 at 20:38
  • 1
    You cannot dependency inject static fields. Remove the static from the field. – M. Deinum Sep 27 '13 at 20:43
  • 1
    What `classpath*:WEB-INF/applicationContext.xml` is supposed to mean? WEB-INF is typically not included as classpath. I think you should specify just `WEB-INF/applicationcContext.xml` if it's in WEB-INF. Likely it's just silently ignored because of the star quantifier. – Boris Treukhov Sep 27 '13 at 20:45
  • @BorisTreukhov yup you're right, that classpath*:whatever/file/path is used when specifying multiple files in the contextConfigLocation separated by a line break and not needed. I made the new parameter value /WEB-INF/lib/applicationContext.xml and I read that if you leave that parameter blank it will look for the file to be named and at the location "/WEB-INF/applicationContext.xml" – Marc Johnson Sep 27 '13 at 21:53
  • @M.Deinum :( so I make the method an instance method and depend on Spring to inject it for me (pretend staticity I guess) and now that class is null. Not only that but it makes perfect sense for the method of the class CheckClassAccess to be static so I probably should be doing this a different way. Still not sure why the things I am adding to my applicationContext.xml do not seem to be getting injected. – Marc Johnson Sep 27 '13 at 22:02
  • The reference can be null only when `@Autowired` is not processed at all. By default(=no-lazyloading) Spring initializes beans eagerily(Fail-Fast design methodology) so that you could catch the autowiring mistakes earlier. So the reference can be null either if your class is not instatiated by Spring at all(newbies often create objects with new opererator and expect Spring to magically postprocess all objects in JVM) or if Spring does not process `@Autowired` because the context misses `context:annotation-config` or `context:component-scan` – Boris Treukhov Sep 28 '13 at 17:22
  • Also please check that you are not examining CGLIB proxy fields (I hope your DAO methods are not final) http://stackoverflow.com/questions/11580911/spring-singleton-bean-fields-are-not-populated – Boris Treukhov Sep 28 '13 at 17:26
  • @BorisTreukhov thanks for all your help. My annotiations aren't being Spring loaded and while I am a newbie, I have not been making my objects by instantiation nor am I missing my contexts. Also I'm using javaassist and my classes aren't final – Marc Johnson Sep 29 '13 at 13:57

2 Answers2

0

If you are using annotations naming matters. So change your StudentDAO as following:

@Autowired
@Qualifier("mySessionFactory")
private SessionFactory sessionFactory;

Look at this for more explanation.

Alternatively Spring recommends @Resource annotation:

@Resource("mySessionFactory")
private SessionFactory sessionFactory;
Ean V
  • 5,091
  • 5
  • 31
  • 39
  • Great info, but not the problem. I've only the one SessionFactory so by type should be fine. To be fair the initial question I asked turned out to not be the problem. I had an old dispatcher servlet still referenced in the web.xml for Spring MVC that I had moved some stuff from to put in the applicationContext.xml and it was complaining. That turned out to be a red herring but after I removed the servlet.xml reference the applicationContext.xml is failing silently to inject anything, right now I'm trying solutions in my comments above. – Marc Johnson Sep 29 '13 at 08:12
0

I was not able to figure out what was going on, but I solved my problem by pulling out my Spring implementation and working with Hibernate directly.

The re-work to use Hibernate only was straight forward:

  • I added in a hibernate.cfg.xml and
  • I removed some Spring managed transaction annotations in the methods of my dao and added that transaction mgmt back in manually
  • I added a static final SessionFactory singleton like https://stackoverflow.com/a/15702946/1411545
  • I removed Spring libs and any stray Spring annotations.

The whole transition took maybe an hour is working well and will allow me to do everything I needed for this project. I think I made a bad initial choice to use Spring here regardless of what did or didn't work.

Thank you all for the many helpful comments and answers.

Community
  • 1
  • 1
Marc Johnson
  • 75
  • 1
  • 12