[RESOLVIDO!] Configurar ambiente web do zero - Hibernate 3.6.1 + Spring 3 + Eclipse?

Bom dia senhores.

 Bom, este é meu primeiro post aqui no forum e sei que este assunto já foi muito discutido, porém mesmo lendo todo material que encontrei não ficou claro para mim como configurar o ambiente do meu projeto para trabalhar com Hibernate Annotations e Spring Framework no Eclipse.

 Meu projeto será uma aplicação web onde o Back-end será no JAVA e o Front-end no Flex 4, os dois se comunicarão via BlazeDS e possuirá a seguinte estrutura:

 [b]Back-end[/b]
     
     Seria mais ou menos algo baseado em MVC, onde existiriam as definições de POJOs num escopo de infraestrutura que se comunicaria com serviços existentes no Controller, estes serviços fariam a comunicação com o Front-end, onde se encontra a camada View. À partir das solicitações da camada View o Controller delegaria o comportamento do Model, onde estariam meus DAO's, por exemplo, e devolveria os resultados a View.
     Eu pretendo implementar o Hibernate neste escopo principalmente para mapear minhas entidades persistentes através de annotations. O suporte para Sessions e Transactions eu pretendo realizar através da integração do Spring com o Hibernate, através do módulo ORM do Spring, onde eu usaria os recursos do Spring para criar minha SessionFactory e faria também o suporte aos DAO's. Além disto, eu pretendo usar o Spring para implementar Injeção de Dependência nas minhas entidades através de seu escopo de BeanFactory proporcionado pelo módulo CORE do mesmo.
     Em relação ao comportamento do Front-end eu não vou me preocupar por enquanto.  

     A minha maior dificuldade está na configuração do Hibernate e do Spring para que eu pudesse chegar neste resultado em meu projeto. Quando digo configurar me refiro a, por exemplo, quais e onde devo criar as bibliotecas do Hibernate; quais e onde devo criar as bibliotecas do Spring; quais arquivos de configuração xml devo criar e qual seria sua estrutura; como faria para carregar estes arquivos de configuração automaticamente na execução da minha aplicação; etc.

     Pretendo trabalhar com o Hibernate 3.6.1 e com o Spring 3.1

     Espero ter sido claro quanto ao meu problema e minhas dúvidas...  :D

Grato desde já.
[]'s

Olá amigo,

No site da devmedia tem uns videos aula que fala sobre isso, eu crio que isso vai te ajudar.

Abraços

Boa tarde… depois de muito tempo estou reabrindo o tópico com uma nova dúvida ainda sobre Spring.

Depois de muito estudar por ai consegui a configuração que eu precisava para montar o ambiente que eu citei no primeiro post deste tópico. No entanto, surgiu um novo problema:

Eu possuo um DAO genérico que estende a classe HibernateDaoSupport do Spring. Este DAO genérico é usado por minha classe de serviço. O problema é que quando rodo minha aplicação o Spring não injeta o DAO na classe de serviço, me ocasionando um NullPointerException. Já tentei usar Annotations do Spring como @Autowired, @Repository, @Service, etc, juntamente com o context:component-scan também. Segui vários tutoriais e li vários post’s, tanto aqui no GUJ quanto em outros fóruns do assunto, mas não consegui resolver meu problema ainda.

Segue meus arquivos de configuração e as classes que mencionei da minha estrutura atual:

applicationContext:

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


    <context:property-placeholder location="/WEB-INF/spring.properties" />

    <!-- DataSource Configuration -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
            <value>${jdbc.driver_class}</value>
        </property>
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
    </bean>

    <!-- Hibernate Configuration -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource">
            <ref local="dataSource" />
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.default_schema">${hibernate.default_schema}</prop>
                <prop key="hibernate.c3p0.min_size">${hibernate.c3p0.min_size}</prop>
                <prop key="hibernate.c3p0.max_size">${hibernate.c3p0.max_size}</prop>
                <prop key="hibernate.c3p0.timeout">${hibernate.c3p0.timeout}</prop>
                <prop key="hibernate.c3p0.max_statements">${hibernate.c3p0.max_statements}</prop>
                <prop key="hibernate.c3p0.idle_test_period">${hibernate.c3p0.idle_test_period}</prop>
            </props>
        </property>

        <property name="configLocation">
            <value>
                classpath:hibernate.cfg.xml
            </value>
        </property>
    </bean>

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

    <bean id="cdtUsuarioService" class="services.administracao.CdtUsuarioService">
        <property name="genericDao" ref="genericDao" />
            
    </bean>

    <bean id="genericDao" class="model.dao.GenericDAO">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>

    <!-- Spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/applicationContext.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>

    <!-- Http Flex Session attribute and binding listener support -->
    <listener>
        <listener-class>flex.messaging.HttpFlexSession</listener-class>
    </listener>
    
    <!-- MessageBroker Servlet -->
    <servlet>
        <servlet-name>MessageBrokerServlet</servlet-name>
        <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
        <init-param>
            <param-name>services.configuration.file</param-name>
            <param-value>/WEB-INF/flex/services-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MessageBrokerServlet</servlet-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

GenericDAO.class:

public class GenericDAO extends HibernateDaoSupport {

    public GenericDAO() {
        
    }

    //... Métodos para Inserir, Atualizar, Deletar e Listar dados.
    
}

CdtUsuarioService.class:

public class CdtUsuarioService extends IServico<CdtUsuario> {

    private GenericDAO genericDao;

    public void setGenericDao(GenericDAO genericDao) {
        this.genericDao = genericDao;
    }

    //... Métodos relacionados aos serviços da classe.

Quando vou usar algum serviço da classe que usa o genericDao ele retorna o NullPointerException pois o DAO não foi injetado. :cry:

O que há de errado nesta estrutura?
Se alguém puder identificar e ajudar a resolver…

Desde já, Obrigado.
[]'s

Boa tarde a todos.

Bom, depois de muita insistência, finalmente consegui fazer o Spring injetar meus benditos beans corretamente e consegui entender o que estava acontecendo. :smiley:

Vamos lá, vou compartilhar com vcs oque aconteceu, para que, diferente de mim, vcs tenham algum suporte aqui no fórum caso passem pela mesma situação.

Primeiramente a causa do problema:
Olhando a estrutura da aplicação que postei anteriormente, logo se ve que trata-se de uma integração envolvendo Hibernate, Spring e BlazeDS.
A principal causa do meu problema se encontrava na estrutura do BlazeDS, pois até então não havia integração com os recursos providos pelo Spring.
O que acontecia na verdade era o seguinte: Quando minha aplicação era iniciada a configuração existente em meu applicationContext se encarregava de montar a BeanFactory do Spring assim como todos os seus recursos. Assim que toda a estrutura do Back-end era carregada o Front-end(Flex) era invocado. Quando eu realizo alguma operação no Front-end que necessite interagir com o Back-end, é o BlazeDS se encarrega desta comunicação (através do channel AMF neste caso), e neste momento ao invés dele fazer referencia aos beans que o Spring já havia carregado ele fazia referencia diretamente nas classes de serviço da minha aplicação, gerando uma nova instancia da mesma.
Todas as dependencias desta nova instancia eram nulas, pois não se tratava dos Beans já carregados pelo Spring. Na verdade o Spring estava injetando os Beans corretamente, mas pelo fato do BlazeDS não estar configurado corretamente eu tinha a impressão de que isto não estava acontecendo.
Para resolver isto foi ralizada uma integração do BlazeDS com o Spring através da classe SpringFactory disponibilizada aqui. Com a classe no projeto bastou configurar os arquivos services-config.xml e remoting-config.xml do Flex para que o BlazeDS passasse a solicitar referencias dos Beans existentes na BeanFactory do Spring ao invés de “instanciar” novas referencias das classes. 8)

Bom vou postar aqui o que foi mudado em relação a estrutura do post anterior para ficar mais claro: :wink:

services-config.xml - Antes:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>

    <services>
        <service-include file-path="remoting-config.xml" />
        <service-include file-path="proxy-config.xml" />
        <service-include file-path="messaging-config.xml" />
    </services>

    <security>
        <login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
    </security>

    <channels>
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>

        <channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
            <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
            </properties>
        </channel-definition>

        <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
            <properties>
                <polling-enabled>true</polling-enabled>
                <polling-interval-seconds>4</polling-interval-seconds>
            </properties>
        </channel-definition>
    </channels>

    <logging>
        <target class="flex.messaging.log.ConsoleTarget"
            level="Error">
            <properties>
                <prefix>[BlazeDS]</prefix>
                <includeDate>true</includeDate>
                <includeTime>false</includeTime>
                <includeLevel>true</includeLevel>
                <includeCategory>true</includeCategory>
            </properties>
            <filters>
                <pattern>Endpoint.*</pattern>
                <pattern>Service.*</pattern>
                <pattern>Message.*</pattern>
                <pattern>DataService.*</pattern>
                <pattern>Configuration</pattern>
            </filters>
        </target>
    </logging>

    <system>
        <redeploy>
            <enabled>true</enabled>
            <watch-interval>20</watch-interval>
            <watch-file>
                {context.root}/WEB-INF/flex/services-config.xml
            </watch-file>
            <watch-file>
                {context.root}/WEB-INF/flex/remoting-config.xml
            </watch-file>
            <touch-file>{context.root}/WEB-INF/web.xml</touch-file>
        </redeploy>
    </system>

</services-config>

services-config.xml - Depois:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>

    <services>
        <service-include file-path="remoting-config.xml" />
        <service-include file-path="proxy-config.xml" />
        <service-include file-path="messaging-config.xml" />
    </services>

    <security>
        <login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
    </security>

    <!-- Spring factory registration -->
    <factories>
        <factory id="spring"
            class="infraestrutura.factory.SpringFactory"/> //FQN da classe SpringFactory.java
    </factories>

    <channels>
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>

        <channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
            <endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
            </properties>
        </channel-definition>

        <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
            <properties>
                <polling-enabled>true</polling-enabled>
                <polling-interval-seconds>4</polling-interval-seconds>
            </properties>
        </channel-definition>
    </channels>

    <logging>
        <target class="flex.messaging.log.ConsoleTarget"
            level="Error">
            <properties>
                <prefix>[BlazeDS]</prefix>
                <includeDate>true</includeDate>
                <includeTime>false</includeTime>
                <includeLevel>true</includeLevel>
                <includeCategory>true</includeCategory>
            </properties>
            <filters>
                <pattern>Endpoint.*</pattern>
                <pattern>Service.*</pattern>
                <pattern>Message.*</pattern>
                <pattern>DataService.*</pattern>
                <pattern>Configuration</pattern>
            </filters>
        </target>
    </logging>

    <system>
        <redeploy>
            <enabled>true</enabled>
            <watch-interval>20</watch-interval>
            <watch-file>
                {context.root}/WEB-INF/flex/services-config.xml
            </watch-file>
            <watch-file>
                {context.root}/WEB-INF/flex/remoting-config.xml
            </watch-file>
            <touch-file>{context.root}/WEB-INF/web.xml</touch-file>
        </redeploy>
    </system>

</services-config>

remoting-config.xml - Antes:

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service" 
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>

    <destination id="UsuarioService">
        <properties>            
            <source>infraestrutura.services.CdtUsuarioService</source>
        </properties>
    </destination>
</service>

remoting-config.xml - Depois:

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service" 
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>

    <destination id="UsuarioService">
        <properties>
            <factory>spring</factory>                 //Referencia da Spring Factory configurada no services-config.xml
            <source>usuarioService</source>     //id ou valor de referencia do Bean existente da BeanFactory do Spring
        </properties>
    </destination>
</service>

Basicamente foram estas as mudanças que fiz. Estou realizando alguns testes para tentar melhorar um pouco a estrutura do Spring para implementar o carregamento dos Beans via Annotation e context:component-scan, mas ainda não concluí.

O material que me ajudou a resolver este problema foi um tutorial de integração de Flex, BlazeDS, Spring e Hibernate disponibilizado no blog de nosso amigo Rodrigo Pereira Fraga, mais conhecido como Digows… Valeu Digows!!! :wink:
Os links para o tutorial são: parte 1 e parte 2

Recomendo a leitura de todo o tutorial e também do material de referência que ele citou. Além disto, a documentação do Spring e do BlazeDS também são de grande ajuda.

Algo que ficou em aberto neste contexto é a questão de Lazy Loading usando o BlazeDS. Eu cheguei a criar um tópico aqui no fórum sobre o assunto: http://www.guj.com.br/java/239874-duvida-sobre-manipulacoa-de-session---hibernate#1237551
Infelizmente ninguém se manifestou :cry:

Bom… é isso ai… obrigado também ao Zenas que indicou o portal da DevMedia. xD
Podem considerar o tópico como RESOLVIDO!

Abraço.
[]'s