Como configurar o Spring?

Olá pessoal!

Hoje eu encuquei que ia aprender a usar o Spring para integrar com o Hibernate. Bem, estou dando uma olhada em alguns livros (principalmente o Spring in Action, Second Edition), mas a configuração do Spring é meio vaga. Talvez seja porque eu já pulei direto para a integração com o hibernate. Enfim, já fiz algumas coisinhas, mas está dando um null pointer exception na hora de salvar um objeto no banco, me parece que ele não está entendendo minha configuração pois não é injetada a SessionFactory dentro do HibernateDaoSupport . Estou postando em anexo o meu projeto do NetBeans beleza? Precisa configurar a as libs para usar o Spring.

Quem pude me dar uma luz eu agradeço!

Abraços!

P.S. Desculpa a burrice, é que estou começando hehehehehe :smiley:

Não uso netbeans.

Que tal postar só o seu arquivo de configuração do Spring?

De qualquer forma, sua aplicação é web? Se sim, você adicionou os ServletListeners do Spring ao web.xml?

Olá LIPE

Eis aqui o spring.xml

[code]

<?xml version="1.0" encoding="UTF-8"?>
<!-- Obtém o arquivo properties -->
<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="hibernate.properties" />
</bean>

<!-- Data Source -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost/testeSpring"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="initialSize" value="5"/>
    <property name="maxActive" value="10"/>
    
</bean>

<!-- Session Factory -->
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    
    <property name="dataSource" ref="dataSource" />
    
    <!-- Classes -->
    <property name="annotatedClasses">
        <list>
            <value>testandospring.Cliente</value>
        </list>
    </property>
    
    <property name="hibernateProperties">
        <props>
            <!-- Buscando no arquivo de properties -->
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
        </props>
    </property>
</bean>

<!-- Template do Hibernate -->
<bean id="hibernateTemplate"
    class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- Configurando os Daos -->
<bean id="clienteDao" class="testandospring.HibernateClienteDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

[/code]

E minha classe de teste

[code]
public class Teste {

public static void main( String[] args ) {
    
    Cliente c = new Cliente();
    c.setNome( "David" );
    c.setSobrenome( "Buzatto" );
    
    Resource configuration =
            new ClassPathResource("testandospring/spring.xml");
    
    BeanFactory factory =
            new XmlBeanFactory( configuration );
    HibernateClienteDao d =
            ( HibernateClienteDao) factory.getBean("clienteDao");
    
    new HibernateClienteDao().salvar( c );
}

}[/code]

Quanto a ser aplicação Web, ela irá ser hehehe. É que eu queria testar o funcionamento antes de partir para a web. É só uma aplicação de teste para eu aprender a tecnologia. Vc poderia então me falar o que eu devo fazer quando foir uma aplicação web ou não? Quais listener devo configurar no web.xml? Mais uma pergunta :smiley: A configuração do spring precisa ser carregada sempre quando for utilizá-lo ou é apenas uma vez na carga da aplicação?

Muito obrigado!

O mapeamento parece correto.

Perguntas:

  1. A classe HibernateClienteDao extende HibernateDaoSupport?
  2. Aparece o log da inicialização da session factory?

Quanto às suas perguntas:

  1. o web.xml deve conter o seguinte:

[code]
contextConfigLocation
classpath:/conf/applicationContext.xml, classpath:/conf/applicationContext-DAOs.xml, classpath:/conf/applicationContext-Services.xml

<!-- para session scoped beans -->
<listener>
	<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>[/code]
  1. Apenas uma vez.

Olá de novo LIPE

Estende sim, dê uma olhada

[code]
public class HibernateClienteDao extends HibernateDaoSupport {

public void salvar( Cliente c ) {
    getHibernateTemplate().saveOrUpdate( c );
}

}[/code]

Olha o log

17/10/2007 12:22:33 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [testandospring/spring.xml] 17/10/2007 12:22:34 org.hibernate.cfg.annotations.Version <clinit> INFO: Hibernate Annotations 3.2.1.GA 17/10/2007 12:22:34 org.hibernate.cfg.Environment <clinit> INFO: Hibernate 3.2.2 17/10/2007 12:22:34 org.hibernate.cfg.Environment <clinit> INFO: loaded properties from resource hibernate.properties: {hibernate.connection.driver_class=com.mysql.jdbc.Driver, hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider, hibernate.max_fetch_depth=1, hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect, hibernate.jdbc.use_streams_for_binary=true, hibernate.format_sql=true, hibernate.query.substitutions=yes 'Y', no 'N', hibernate.proxool.pool_alias=pool1, hibernate.connection.username=root, hibernate.cache.region_prefix=hibernate.test, hibernate.connection.url=jdbc:mysql://localhost/testeSpring, hibernate.bytecode.use_reflection_optimizer=false, hibernate.connection.password=****, hibernate.jdbc.batch_versioned_data=true, hibernate.connection.pool_size=1} 17/10/2007 12:22:34 org.hibernate.cfg.Environment <clinit> INFO: using java.io streams to persist binary types 17/10/2007 12:22:34 org.hibernate.cfg.Environment buildBytecodeProvider INFO: Bytecode provider name : cglib 17/10/2007 12:22:34 org.hibernate.cfg.Environment <clinit> INFO: using JDK 1.4 java.sql.Timestamp handling 17/10/2007 12:22:34 org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory INFO: Building new Hibernate SessionFactory 17/10/2007 12:22:34 org.hibernate.cfg.AnnotationBinder bindClass INFO: Binding entity from annotated class: testandospring.Cliente 17/10/2007 12:22:34 org.hibernate.cfg.annotations.EntityBinder bindTable INFO: Bind entity testandospring.Cliente on table Cliente 17/10/2007 12:22:34 org.hibernate.connection.ConnectionProviderFactory newConnectionProvider INFO: Initializing connection provider: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: RDBMS: MySQL, version: 5.0.15-nt 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.0.4 ( $Date: 2006-10-19 17:47:48 +0200 (Thu, 19 Oct 2006) $, $Revision: 5908 $ ) 17/10/2007 12:22:35 org.hibernate.dialect.Dialect <init> INFO: Using dialect: org.hibernate.dialect.MySQLDialect 17/10/2007 12:22:35 org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory INFO: Using default transaction strategy (direct JDBC transactions) 17/10/2007 12:22:35 org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended) 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Automatic flush during beforeCompletion(): disabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Automatic session close at end of transaction: disabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: JDBC batch size: 15 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: JDBC batch updates for versioned data: enabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Scrollable result sets: enabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: JDBC3 getGeneratedKeys(): enabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Connection release mode: on_close 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Maximum outer join fetch depth: 1 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Default batch fetch size: 1 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Generate SQL with comments: disabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory buildSettings INFO: Order SQL updates by primary key: disabled 17/10/2007 12:22:35 org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory 17/10/2007 12:22:35 org.hibernate.hql.ast.ASTQueryTranslatorFactory <init> INFO: Using ASTQueryTranslatorFactory 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Query language substitutions: {no='N', yes='Y'} 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: JPA-QL strict compliance: disabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Second-level cache: enabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Query cache: disabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory createCacheProvider INFO: Cache provider: org.hibernate.cache.HashtableCacheProvider 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Optimize cache for minimal puts: disabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Cache region prefix: hibernate.test 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Structured second-level cache entries: disabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Statistics: disabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Deleted entity synthetic identifier rollback: disabled 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Default entity-mode: pojo 17/10/2007 12:22:36 org.hibernate.cfg.SettingsFactory buildSettings INFO: Named query checking : enabled 17/10/2007 12:22:36 org.hibernate.impl.SessionFactoryImpl <init> INFO: building session factory 17/10/2007 12:22:36 org.hibernate.impl.SessionFactoryObjectFactory addInstance INFO: Not binding factory to JNDI, no JNDI name configured Exception in thread "main" java.lang.NullPointerException at testandospring.HibernateClienteDao.salvar(HibernateClienteDao.java:22) at testandospring.Teste.main(Teste.java:37) Java Result: 1

Quanto as configurações do web.xml, eu tenho que fazer mesmo se não for usar o Spring MVC?

Valeu!

Mais uma pergunta:

Os arquivos

conf/applicationContext.xml
conf/applicationContext-DAOs.xml
e conf/applicationContext-Services.xml

Eu devo criar ou já são parte do Spring?

Eles são os arquivos de configuração de um projeto aqui. São equivalentes ao seu spring.xml.

Hm, tenho um palpite sobre porquê não funcionou. Normalmente declaramos um transaction manager, que é um interceptor aplicado aos métodos da classe que usa o DAO.

Então, no seu caso, falta fazer o seu DAO entender que deve abrir uma transação antes do método “salvar” ser executado e commita-la após terminar.

Se estiver utilizando Java 5 e annotations, basta seguir este tutorial:
http://www.springframework.org/docs/reference/transaction.html
Mas ao invés de aplicar o interceptor no Service, aplicará diretamente no DAO.

Olá LIPE.

Consegui resolver, segui seu padrão de arquivos de configuração e tinha um erro grotesco na minha classe de teste… Olha lá

[code]
HibernateClienteDao d =
( HibernateClienteDao) factory.getBean(“clienteDao”);

    new HibernateClienteDao().salvar( c );  [/code]

Estava criando um HibernateClienteDao do nada, sem usar o que eu tinha obtido… hehehe

Quanto a transação vou ver isso agora.

Agora mais uma pergunta, fiz um servlet para testar aqui. Como faço para obter o bean configurado no Spring dentro do servlet? No meu teste eu carrego na mão e uso a configuração.

Valeu pela ajuda :smiley:

haha olha só.

Servlets? Você não vai MESMO usar servlets, né? :smiley:

O ideal é integrar o Spring com seu WebFramework de preferência, configurando de forma que o Spring crie suas Actions/Commands/Services, automatizando a injeção de dependências.

Se for seguir este caminho, recomendo o DWR.

Não, não vou usar servlets, só estou testando.

Deixa eu explicar o que está acontecendo para vc entender.

Tenho uma aplicação para desenvolver que terá que usar o Flex. Para facilitar minha vida na persistência eu vou usar o Hibernate, mas eu não quero ficar abrindo/fechando sessões do Hibernate. Queria deixar isso a cargo do Spring. Só vou usar o Spring única e exclusivamente para dar uma mão com o Hibernate, nada mais.

Por isso queria saber, como obter um bean que foi configurado entendeu?

Abraço!

Bom, atualmente estou trabalhando com 2 projetos razoavelmente grandes utilizando Flex (com dataservices), Hibernate e Spring hehe

Para delegar ao Spring a função de criar os Delegates/Services/etc que o Flex chama, basta fazer o seguinte:

  1. Adicionar o seguinte antes do fechamento da tag do arquivo /WEB-INF/flex/services-config.xml

<factories> <factory id="springFactory" class="meu.pacote.SpringFactory"/> </factories>
2. Adicionar o seguinte antes do fechamento da tag do arquivo /WEB-INF/flex/remoting-config.xml

	<destination id="usuarioService">
		<properties>
			<factory>springFactory</factory>
			<source>usuarioService</source>
		</properties>
	</destination>

Sendo o ID do bean configurado no seu spring.xml e o atributo “id” o source que será usado no RemoteObject do Flex.

  1. E o código do SpringFactory:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import flex.messaging.FactoryInstance;
import flex.messaging.FlexFactory;
import flex.messaging.config.ConfigMap;
import flex.messaging.services.ServiceException;

/**
 * *
 * 
 * @author Jeff Vroom
 */
public class SpringFactory implements FlexFactory
{

	private static final String	SOURCE	= "source";

	/**
	 * This method can be used to initialize the factory itself. It is called
	 * with configuration parameters from the factory tag which defines the id
	 * of the factory.
	 */
	public void initialize( String id, ConfigMap configMap )
	{}

	/**
	 * This method is called when we initialize the definition of an instance
	 * which will be looked up by this factory. It should validate that the
	 * properties supplied are valid to define an instance. Any valid properties
	 * used for this configuration must be accessed to avoid warnings about
	 * unused configuration elements. If your factory is only used for
	 * application scoped components, this method can simply return a factory
	 * instance which delegates the creation of the component to the
	 * FactoryInstance's lookup method.
	 */
	public FactoryInstance createFactoryInstance( String id, ConfigMap properties )
	{
		SpringFactoryInstance instance = new SpringFactoryInstance( this, id, properties );
		instance.setSource( properties.getPropertyAsString( SOURCE, instance.getId() ) );
		return instance;
	} // end method createFactoryInstance()

	/**
	 * Returns the instance specified by the source and properties arguments.
	 * For the factory, this may mean constructing a new instance, optionally
	 * registering it in some other name space such as the session or JNDI, and
	 * then returning it or it may mean creating a new instance and returning
	 * it. This method is called for each request to operate on the given item
	 * by the system so it should be relatively efficient.
	 * <p>
	 * If your factory does not support the scope property, it report an error
	 * if scope is supplied in the properties for this instance.
	 */
	public Object lookup( FactoryInstance inst )
	{
		SpringFactoryInstance factoryInstance = ( SpringFactoryInstance ) inst;
		return factoryInstance.lookup();
	}

	static class SpringFactoryInstance extends FactoryInstance
	{
		SpringFactoryInstance( SpringFactory factory, String id, ConfigMap properties )
		{
			super( factory, id, properties );
		}

		@Override
		public String toString()
		{
			return "SpringFactory instance for id=" + getId() + " source=" + getSource() + " scope=" + getScope();
		}

		@Override
		public Object lookup()
		{
			ApplicationContext appContext = WebApplicationContextUtils
					.getWebApplicationContext( flex.messaging.FlexContext.getServletConfig().getServletContext() );
			String beanName = getSource();

			try
			{
				return appContext.getBean( beanName );
			}
			catch( NoSuchBeanDefinitionException nexc )
			{
				ServiceException e = new ServiceException();
				String msg = "Spring service named '" + beanName + "' does not exist.";
				e.setMessage( msg );
				e.setRootCause( nexc );
				e.setDetails( msg );
				e.setCode( "Server.Processing" );
				throw e;
			}
			catch( BeansException bexc )
			{
				ServiceException e = new ServiceException();
				String msg = "Unable to create Spring service named '" + beanName + "' ";
				e.setMessage( msg );
				e.setRootCause( bexc );
				e.setDetails( msg );
				e.setCode( "Server.Processing" );
				throw e;
			}
		}

	}
}

Se você não vai comprar o servidor do Flex, pode usar o Granite (google), que faz as mesma coisa, mas sem o push de dados.

Mas, respondendo sua dúvida sobre Servlets, não sei como configurar para o Spring criá-los, de forma que injetasse as dependências.

Ola LIPE.

Obrigado pelas respostas.

Então, não usaremos o Flex Data Services, pois ainda estamos engatinhando na tecnologia, e infelizmente não temos verba para treinamento, é tudo aprendido na raça infelizmente.

O que eu precisava eu encontrei dentro da implementação da SpringFactory que você postou, eu não queria criar servlets e injetar dependências nos mesmos, queria simplesmente pegar um bean que foi criado. Eu quase cheguei no que vc postou, passei raspando :smiley:

Agora a última pergunta, prometo :smiley:

O Spring me garante o fechamento de sessão do hibernate né?

Abraço!

Se você configurar o TransactionInterceptor direitinho, sim.

Quanto ao DataServices, não tem muito que aprender. Configurando o services-config.xml e remoting-config.xml, no flex basta fazer algo como:

protected var service:RemoteObject  = new RemoteObject( "usuarioService" );
service.source = "usuarioService";
service.addEventListener(InvokeEvent.INVOKE, invoke);
service.addEventListener(ResultEvent.RESULT, result);
service.addEventListener(FaultEvent.FAULT, fault);

service.savePessoa( pessoa );

Valeu pelas dicas LIPE!

Abraço!

E ai caras tudo beleza.

Eu estou a desenvolver uma aplicacao web e to querendo usar o spring. Ja encontrei alguns tutoriais que explicam o que devo configurar para comecar, mas eu nao entendo por exemplo para que server o listener e o filtre.

Sera que podem explicar-me ou indicar um tutorial onde expliquem isso?

Obrigado.

Quais são as bibliotecas necessárias para rodar utilizar o spring?

já tenho todos os arquivos de configuração só não sei quais são as biblioteca atuais, que são necessárias para rodar o spring em um sistema web

Tenho o marven instalado no eclipse 3.7, mais ele é só um complemento para gerencias as dependencias.

Bem baixei o arquivo spring-framework-3.1.0.RELEASE-with-docs, segundo o site é a ultima versão do spring. Porém quando descompactei notei os seguintes arquivos

  • dist
  • docs
  • projects

dentro de cada pasta desta há diversas bibliotecas, quais devo utilizar?

att.

Algumas bibliotecas mudam do spring 2.XX para o 3.XX. Por isso fique atento na migração segui um tutorial interessante.

http://www.roseindia.net/spring/spring3/spring-3-hello-world.shtml

att.