JPA com JNDI e Toplink na Locaweb

Estou tentando usar a JPA da Toplink com uma coneção por JNDI configurada pela Locaweb e não funciona. Minha aplicação não reconhece de forma alguma o “nome” de jndi que me passaram.

Reclamei em um chamado e responderam que a configuração realmente estava errada. :x Corrigiram e fizeram um teste na minha área com uma conexão em JSP que funciona:

Context context = new InitialContext();
Context lautx = (Context) context.lookup("java:comp/env");
ds = (DataSource)lautx.lookup("jdbc/jndiname");
conexao = ds.getConnection();
out.write("Conectado via JNDI!<br><br>");
Statement stmt= conexao.createStatement();
conexao.close();

Mas eu preciso que funcione com JPA… Aqui na minha máquina funciona (tomcat configurado por mim)
Alguém sabe se tem algum outro macete que preciso configurar para conseguir usar a persistência por JPA? :?: :?:
Minha configuração por JPA:

&lt;persistence-unit name="newsPU" transaction-type="JTA"&gt;
    &lt;provider&gt;oracle.toplink.essentials.PersistenceProvider&lt;/provider&gt;
    &lt;jta-data-source&gt;jdbc/jndiname&lt;/jta-data-source&gt;
    &lt;properties/&gt;
  &lt;/persistence-unit&gt;

Erro que aparece no log:

Caused by: javax.persistence.PersistenceException: Exception [TOPLINK-7060] 
(Oracle TopLink Essentials - 9.1 (Build b27)): oracle.toplink.esse
ntials.exceptions.ValidationException
Exception Description: Cannot acquire data source [jdbc/jndiname].
Internal Exception: javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy
(EntityManagerSetupImpl.java:180)    at oracle.toplink.essentials.internal.ejb.cmp3.base.
EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:78)        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl
(EntityManagerFactoryImpl.java:113
)

A propósito, tenho JVM dedicado.

Minha experiência com a locaweb não foi nada boa, sempre tive problemas parecidos com o seu.
As vezes levava dias para conseguir depurar o problema e mais dias para conseguir que alguém resolvesse. Por isto que agora o PJ é hospedado pela RoseHosting, que eu recomendo.

Eu não sei como é este plano novo, de JVM dedicada, mas como você escreveu “a jndi que me passaram” eu imagino que o suporte da Locaweb ainda seja responsável por algumas configurações, provavelmente para não haver conflito de nomes na mesma rede.

Eu não entendi porque o suporte precisa configurar o nome do serviço pra você, se teoricamente você, o plano oferece JVM dedicada e você poderia rodar o tomcat (ou outro) neste JVM. Não pode?

O meu conselho, apesar de não ajudar muito, é você colocar uma classe de teste que sobe um serviço JNDI e depois tentar “encontrá-lo”. Se isto não funcionar, a Locaweb tá fazendo algum tipo de restrição na rede ou na API de redes das JVMs.

Consegui!
Eu realmente quase saí da Locaweb… Mas um atendente do help desk hoje ligou em meu cel e eu o ajudei a configurar a JNDI corretamente no tomcat, hehehe

Mesmo assim tive que criar uma outra classe para a sessão da Toplink.

O HelpDesk da Locaweb me ajudou a encontrar a solução, no fórum da Oracle http://kr.forums.oracle.com/forums/thread.jspa?threadID=519351&tstart=127

Tenho que criar uma classe para prover a sessão de login:

public class ToplinkSessionCustomizer implements SessionCustomizer {

	/**
	 * Construtor
	 */
	public ToplinkSessionCustomizer() {
		super();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer#customize(oracle.toplink.essentials.sessions.Session)
	 */
	public void customize(Session session) throws Exception {
		JNDIConnector connector = (JNDIConnector) session.getLogin()
				.getConnector();
		connector.setLookupType(JNDIConnector.STRING_LOOKUP);
	}
}[/code]

E em meu persistence.xml:

[code]&lt;persistence-unit name="newsPU" transaction-type="JTA"&gt;
		&lt;provider&gt;
			oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
		&lt;/provider&gt;
		&lt;jta-data-source&gt;java:comp/env/jdbc/jndiname&lt;/jta-data-source&gt;
&lt;properties&gt;
			&lt;property name="toplink.session.customizer" value="a.b.c.ToplinkSessionCustomizer" /&gt;

Pronto, a jndi é encontrada!

Vale lembrar que tudo isso é porque a Locaweb que configura a JNDI no tomcat deles… O ideal é fazer um arquivo de contexto e configurar na aplicação.

Oi,

estou com o mesmo problema porém ainda não consegui resolver, mesmo realizando os procedimentos informados.

public class testeclass {

    public static EntityManagerFactory emf = Persistence.createEntityManagerFactory("ReservaPassagensEJBPU2");
    
    public void persist(Object object) {
        try {
            EntityManager em = null;
            
            em = emf.createEntityManager();
            em.getTransaction().begin();
            
            em.persist(object);
            
            em.getTransaction().commit();
            
        } catch (Exception e) {
            java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, "exception caught", e);
            throw new RuntimeException(e);
        }
    }

}
public class ToplinkSessionCustomizer implements SessionCustomizer {
    public ToplinkSessionCustomizer() {   
        super();   
    }  
    
    public void customize(Session session) throws Exception{
        JNDIConnector connector = (JNDIConnector) session.getLogin().getConnector();
        connector.setLookupType(JNDIConnector.STRING_LOOKUP);
    }
}

Minha persistence.xml está da seguinte forma:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="ReservaPassagensEJBPU2" transaction-type="JTA">
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
    <jta-data-source>SistResevaBanco</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="toplink.session.customizer" value="br.com.reserva.teste.ToplinkSessionCustomizer"/>
    </properties>
  </persistence-unit>
</persistence>

na linha

em = emf.createEntityManager();

e está me gerando o seguinte erro:

21/11/2008 21:18:59 br.com.reserva.teste.testeclass persist
SEVERE: exception caught
javax.persistence.PersistenceException: Exception [TOPLINK-7060] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: Cannot acquire data source [SistResevaBanco].
Internal Exception: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:239)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:93)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:126)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:120)
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:91)
        at br.com.reserva.teste.testeclass.persist(testeclass.java:24)
        at br.com.reserva.teste.testaEJB.main(testaEJB.java:36)
Caused by: Exception [TOPLINK-7060] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: Cannot acquire data source [SistResevaBanco].
Internal Exception: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at oracle.toplink.essentials.exceptions.ValidationException.cannotAcquireDataSource(ValidationException.java:373)
        at oracle.toplink.essentials.jndi.JNDIConnector.connect(JNDIConnector.java:135)
        at oracle.toplink.essentials.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:184)
        at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:582)
        at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:280)
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:229)
        ... 6 more
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
        at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
        at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
        at javax.naming.InitialContext.lookup(InitialContext.java:392)
        at oracle.toplink.essentials.jndi.JNDIConnector.connect(JNDIConnector.java:127)
        ... 10 more
java.lang.RuntimeException: javax.persistence.PersistenceException: Exception [TOPLINK-7060] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: Cannot acquire data source [SistResevaBanco].
Internal Exception: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at br.com.reserva.teste.testeclass.persist(testeclass.java:33)
        at br.com.reserva.teste.testaEJB.main(testaEJB.java:36)
Caused by: javax.persistence.PersistenceException: Exception [TOPLINK-7060] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: Cannot acquire data source [SistResevaBanco].
Internal Exception: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:239)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:93)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:126)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:120)
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:91)
        at br.com.reserva.teste.testeclass.persist(testeclass.java:24)
        ... 1 more
Caused by: Exception [TOPLINK-7060] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: Cannot acquire data source [SistResevaBanco].
Internal Exception: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at oracle.toplink.essentials.exceptions.ValidationException.cannotAcquireDataSource(ValidationException.java:373)
        at oracle.toplink.essentials.jndi.JNDIConnector.connect(JNDIConnector.java:135)
        at oracle.toplink.essentials.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:184)
        at oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:582)
        at oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:280)
        at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:229)
        ... 6 more
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)
        at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
        at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325)
        at javax.naming.InitialContext.lookup(InitialContext.java:392)
        at oracle.toplink.essentials.jndi.JNDIConnector.connect(JNDIConnector.java:127)
        ... 10 more

fico no aguardo,

Obrigado