Hi Dominique,
sounds reasonable to do that ...
... please find sample code at the end of this email (JCATest.java,
JCATestRemoteInterface.java, JCATestLocal.java) - Note, that I have not
tested this code (it should however compile and work in JBoss 4.0.5GA
with ejb3 profile enabled, Java 1.5, and Jackrabbit 1.3.1)
hope this helps to reproduce the "problem"
kind regards,
Markus
********************FILE ATTACHMENTS**************************
---------------------------JCATest.java---------------------------------------------
import java.util.Calendar;
import javax.ejb.Remote;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.BindingType;
import org.jboss.annotation.ejb.LocalBinding;
import org.jboss.annotation.ejb.RemoteBinding;
import javax.annotation.Resource;
@javax.jws.WebService(name="JCATest",
targetNamespace="http://jackrabbit.apache.org/test", serviceName="JCATest")
@Stateless(mappedName="jackrabbit/JCATest")
@Local(JCATestLocal.class)
@Remote(JCATestRemoteInterface.class)
@LocalBinding(jndiBinding="jackrabbit/JCATestLocal")
@RemoteBinding(jndiBinding="jackrabbit/JCATestRemoteInterface")
@BindingType(value="http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true")
@javax.jws.soap.SOAPBinding(style = SOAPBinding.Style.RPC)
public class JCATest implements JCATestRemoteInterface, JCATestLocal {
@Resource(mappedName="java:jcr/local",
type=javax.jcr.Repository.class,
authenticationType=javax.annotation.Resource.AuthenticationType.CONTAINER)
Repository repo;
@javax.jws.WebMethod()
public String createTestNode(String userName, String password) {
try {
Credentials cred = new SimpleCredentials(userName,
password.toCharArray());
Session session = repo.login(cred, null);
Node rootNode = session.getRootNode();
Node newNode = rootNode.addNode("newNode", "nt:unstructured");
newNode.setProperty("jcr:lastModified", Calendar.getInstance());
session.save();
return newNode.getUUID();
} catch (Exception e) { e.printStackTrace(); return "";}
}
}
---------------------------JCATest.java---------------------------------------------
---------------------------JCATestRemoteInterface.java---------------------------------------------
public interface JCATestRemoteInterface {
String createTestNode(String userName, String password);
}
---------------------------JCATestRemoteInterface.java---------------------------------------------
---------------------------JCATestLocal.java---------------------------------------------
public interface JCATestLocal {
String createTestNode(String userName, String password);
}
---------------------------JCATestLocal.java---------------------------------------------
********************FILE ATTACHMENTS**************************
Dominique Pfister schrieb:
Hi Markus,
that's great news! Before adding this to jcr-ds.xml, I'd like to
understand why this setting makes the resource adapter work: as far as
I understand, it is meant to overcome a limitation on the datasource
side and I don't see what Jackrabbit's resource adapter is doing wrong
that makes this setting necessary. Can you possibly provide a small
test EJB/application and guide that helps reproducing this "no
transaction" error? If it really turned out to be some missing
functionality in our resource adapter that could also affect other
application servers I'd rather like to fix that.
Kind regards
Dominique
On 16/08/07, Markus Reis <[EMAIL PROTECTED]> wrote:
Hi Dominique,
I finally solved the problem ... The "trick" was to set
<track-connection-by-tx/> in the jcr-ds.xml datasource configuration; It
should be:
<connection-factories>
<tx-connection-factory>
<jndi-name>jcr/local</jndi-name>
<xa-transaction/>
<rar-name>jackrabbit-jca-1.3.1.rar</rar-name>
<track-connection-by-tx/>
<connection-definition>javax.jcr.Repository</connection-definition>
<config-property name="homeDir"
type="java.lang.String">${jboss.server.data.dir}${/}jackrabbit</config-property>
<config-property name="configFile"
type="java.lang.String">classpath:repository.xml</config-property>
<config-property name="bindSessionToTransaction"
type="java.lang.Boolean">true</config-property>
</tx-connection-factory>
</connection-factories>
Further information on this property can be found under:
http://docs.jboss.org/jbossas/jboss4guide/r2/html/ch7.chapt.html#ch7.xaconf.fig
I think that we/you/someone (Jukka) should update
jackrabbit-jca\deploy\jboss\4.x\jcr-ds.xml accordingly - What do you think?
kind regards,
Markus
Markus Reis schrieb:
Hi Dominique,
ejb-jar.xml and jboss.xml are deployment descriptors necessary for
EJB2.x - I (would like to) use annotations and dependency injection
(as proposed for EJB3.x) instead.
Nevertheless I tried to change my code according to your suggestions:
//new field:
@Resource(mappedName="java:jcr/local",
type=javax.jcr.Repository.class,
authenticationType=javax.annotation.Resource.AuthenticationType.CONTAINER)
Repository repo;
//changed method excerpt:
Credentials cred = new
SimpleCredentials(path.getUsername(), path.getPassword());
session = repo.login(cred, null);
Node root = session.getRootNode();
Node child = root.hasNode(path.getRelativePath()) ?
root.getNode(path.getRelativePath()) : createFilePath(root,
path.getPathParts(), path.getObjectName());
FileTypeResolver ftr = FileTypeResolver.instantiate();
child.setProperty("jcr:mimeType", ftr.getMIMEType(obj));
child.setProperty("jcr:data", new FileInputStream(obj));
Calendar rightNow = Calendar.getInstance();
child.setProperty("jcr:lastModified", rightNow);
session.save();
I annotated the method with:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
This should be the default setting, but who knows ...
I used the following datasource config:
<connection-factories>
<tx-connection-factory>
<jndi-name>jcr/local</jndi-name>
<xa-transaction/>
<rar-name>jackrabbit-jca-1.3.1.rar</rar-name>
<connection-definition>javax.jcr.Repository</connection-definition>
<config-property name="homeDir"
type="java.lang.String">${jboss.server.data.dir}${/}jackrabbit</config-property>
<config-property name="configFile"
type="java.lang.String">classpath:repository.xml</config-property>
<config-property name="bindSessionToTransaction"
type="java.lang.Boolean">true</config-property>
</tx-connection-factory>
</connection-factories>
Debugging my code I found out that everything works fine until and
after session.save() - When the method returns however it seems that a
commit takes place (calling XASessionImpl.end()) and this commit is
not successful due to a missing transaction:
143394 [http-0.0.0.0-8080-3] ERROR
org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS - SOAP request exception
java.lang.RuntimeException: org.jboss.tm.JBossRollbackException:
Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257,
GlobalId=dme018/14, BranchQual=, localId=14]
status=STATUS_NO_TRANSACTION; - nested throwable:
(javax.transaction.xa.XAExc
eption)
at
org.jboss.aspects.tx.TxPolicy.handleEndTransactionException(TxPolicy.java:198)
at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:180)
at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87)
at
org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at
org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at
org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at
org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
at
org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:102)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at
org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at
org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
at
org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:211)
at
org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:173)
at
org.jboss.ws.integration.jboss42.ServiceEndpointInvokerEJB3.invokeServiceEndpoint(ServiceEndpointInvokerEJB3.jav
a:114)
at
org.jboss.ws.core.server.AbstractServiceEndpointInvoker.invoke(AbstractServiceEndpointInvoker.java:173)
at
org.jboss.ws.core.server.ServiceEndpoint.handleRequest(ServiceEndpoint.java:204)
at
org.jboss.ws.core.server.ServiceEndpointManager.processSOAPRequest(ServiceEndpointManager.java:440)
at
org.jboss.ws.core.server.AbstractServiceEndpointServlet.doPost(AbstractServiceEndpointServlet.java:114)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at
org.jboss.ws.core.server.AbstractServiceEndpointServlet.service(AbstractServiceEndpointServlet.java:75)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at
org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
at
org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at
org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at
org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:66
4)
at
org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at
org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:595)
Caused by: org.jboss.tm.JBossRollbackException: Unable to commit,
tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=dme018/
14, BranchQual=, localId=14] status=STATUS_NO_TRANSACTION; - nested
throwable: (javax.transaction.xa.XAException)
at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:372)
at org.jboss.tm.TxManager.commit(TxManager.java:240)
at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175)
... 43 more
Caused by: javax.transaction.xa.XAException
at
org.apache.jackrabbit.core.XASessionImpl.end(XASessionImpl.java:279)
at
org.apache.jackrabbit.jca.TransactionBoundXAResource.end(TransactionBoundXAResource.java:46)
at
org.jboss.tm.TransactionImpl$Resource.endResource(TransactionImpl.java:2143)
at
org.jboss.tm.TransactionImpl$Resource.endResource(TransactionImpl.java:2118)
at
org.jboss.tm.TransactionImpl.endResources(TransactionImpl.java:1462)
at
org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1116)
at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
... 45 more
I really don't know why this happens - Do you have any other idea?
Do you know somebody who may have tested the XASessionImpl in a JBoss
EJB3 SLSB (I saw that Jukka added/committed the jcr-ds.xml file)?
kind regards and many thanks,
Markus
Dominique Pfister schrieb:
Hi Markus
and what about creating references in the local JNDI namespace instead
of directly referencing objects in the global one? I found a section
talking about resource references within XML deployment descriptors in
this JBoss EJB 3.0 tutorial:
http://docs.jboss.com/ejb3/app-server/tutorial/jboss_resource_ref/jboss_rr.html
Does that help?
Dominique
On 8/7/07, Markus Reis <[EMAIL PROTECTED]> wrote:
Hi Dominique,
here's where it really gets strange - I'm also accessing the jackrabbit
repository through my own JSF application using:
InitialContext context = new InitialContext();
Repository repository = (Repository)
context.lookup("java:jcr/local");
SimpleCredentials credentials = new
SimpleCredentials(username, password.toCharArray());
Session session = repository.login(credentials);
and subsequent operations on the repository in this session work
without
any problems.
Then I have an EJB (3.0, SLSB) with the following code:
InitialContext ctx = new InitialContext();
Repository repo = (Repository)ctx.lookup("java:jcr/local");
Credentials cred = new
SimpleCredentials(path.getUsername(),
path.getPassword());
Session session = repo.login(cred, null);
and here subsequent calls bring up the reported problems.
Do you have any idea what is wrong in the EJB (or what I could try
alternatively - Do I have to add certain annotations regarding CMT?)?
many thanks,
Markus
Dominique Pfister schrieb:
Hi Markus,
I don't know whether your client code resides in a servlet or EJB, but
this is what I did to access the repository from a sample JSP page
containing the following code snippet:
InitialContext ctx = new InitialContext();
Repository repository = (Repository)
ctx.lookup("java:comp/env/jcr/repository");
(1) inside the web application's web.xml file I declared the
reference:
<resource-ref>
<description>Jackrabbit</description>
<res-ref-name>jcr/repository</res-ref-name>
<res-type>javax.jcr.Repository</res-type>
<res-auth>Container</res-auth>
</resource-ref>
(2) inside the web application's jboss-web.xml file I linked the
reference to
the actual datasource:
<resource-ref>
<res-ref-name>jcr/repository</res-ref-name>
<res-type>javax.jcr.Repository</res-type>
<jndi-name>java:jcr/local</jndi-name>
</resource-ref>
As far as I can tell - I'm not a JBoss expert - the exception in that
other post is caused by accessing the global data source directly
instead of declaring a reference to it in the web application
descriptor.
Dominique
On 8/6/07, Markus Reis <[EMAIL PROTECTED]> wrote:
Hi Dominique,
that's exactly what I expected as well - however if I execute the
code
as is (i.e. without the surrounding XA stuff), I get an exception
that
tells me that no transaction has been started
(STATUS_NO_TRANSACTION) -
my exception is very similar to what has been reported at
http://mail-archives.apache.org/mod_mbox/jackrabbit-dev/200702.mbox/[EMAIL
PROTECTED]
Therefore I tried to start the transaction myself ...
... any further help/guidance/hints is/are highly appreciated ...
kind regards,
Markus
-------- Original-Nachricht --------
Betreff: Re: JBoss and Jackrabbit JCA
Datum: Mon, 6 Aug 2007 16:25:01 +0200
Von: Dominique Pfister <[EMAIL PROTECTED]>
Antwort an: [email protected]
An: [email protected]
Referenzen: <[EMAIL PROTECTED]>
Hi Markus,
Apparently, your session is already associated with a transaction. I
don't unterstand why you'd want to access the XAResource directly in
your client code. I'd expect that if you left only your core code
(starting with the comment "// .... add new nodes & properties and
save them") JBoss would automatically execute the surrounding code
you
inserted manually.
Kind regards
Dominique
On 8/6/07, Markus Reis <[EMAIL PROTECTED]> wrote:
Dear All,
I'm currently playing around with Jackrabbit's jca package and
end up in
some strange errors (which will mainly be due to wrong use from
my code
:-)). Here's my environment:
JBoss 4.0.5.GA
Java 1.5_06
Jackrabbit 1.3.1 (checked out and build tagged version)
jcr-ds.xml (only modified homeDir property - I experimented with
both
true and false for bindSessionToTransaction):
<connection-factories>
<tx-connection-factory>
<jndi-name>jcr/local</jndi-name>
<xa-transaction/>
<rar-name>jackrabbit-jca-1.3.1.rar</rar-name>
<connection-definition>javax.jcr.Repository</connection-definition>
<config-property name="homeDir"
type="java.lang.String">${jboss.server.data.dir}${/}jackrabbit</config-property>
<config-property name="configFile"
type="java.lang.String">classpath:repository.xml</config-property>
<config-property name="bindSessionToTransaction"
type="java.lang.Boolean">false</config-property>
</tx-connection-factory>
</connection-factories>
Here's my client code:
XAResource xares =
((JCASessionHandle)session).getManagedConnection().getXAResource();
//xares is either of type
org.apache.jackrabbit.core.XASessionImpl (if
bindSessionToTransaction is set to false and
org.apache.jackrabbit.jca.TransactionBoundXAResource if set to true)
// create dummy Xid
Xid xid = new XidImpl(counter++); //XidImpl is simply copied
from
org.apache.jackrabbit.core.UserTransactionImpl
((org.apache.jackrabbit.core.XASessionImpl)xares).associate(null);
//I think I shouldn't do that :-)
xares.start(xid, XAResource.TMNOFLAGS);
// .... add new nodes & properties and save them
Node root = session.getRootNode();
Node child = root.hasNode(path.getRelativePath()) ?
root.getNode(path.getRelativePath()) : createFilePath(root,
path.getPathParts(), path.getObjectName());
FileTypeResolver ftr = FileTypeResolver.instantiate();
child.setProperty("jcr:mimeType", ftr.getMIMEType(obj));
child.setProperty("jcr:data", new FileInputStream(obj));
Calendar rightNow = Calendar.getInstance();
child.setProperty("jcr:lastModified", rightNow);
//child.setProperty("original-file-name",
obj.getName());
session.save();
xares.end(xid, XAResource.TMSUCCESS);
xares.prepare(xid);
xares.commit(xid, false);
If I set bindSessionToTransaction to false and disassociate the
XAResource from it's transaction (calling associate(null)), I can
start
(and end and commit) the transaction successfully - I have
however the
strong feeling that I shouldn't do that :-)
If I set bindSessionToTransaction to true (which would be the
default)
or if I do not disassociate the XAResource from it's transaction
then I
always get an exception thrown at XASessionImpl line 227
(remember that
I'm working on 1.3.1).
I never found out why the XAResource was associated with a
transaction
although bindSessionToTransaction was set to false.
It would be great if someone could tell me what I'm doing wrong
and/or
point me to sample code that should work in my environment and/or
tell
me if she/he already did something similar successfully when
deployed on
JBoss.
many thanks,
Markus
--
Mag. Markus Reis
Austrian Research Centers GmbH - ARC
Research Studios
Studio Digital Memory Engineering
Thurngasse 8/3/20, A-1090 Wien
Mobile: +43 664 825 1106
Tel.: +43-1-585 05 37 - 16
Fax: +43-1-585 37 41
<[EMAIL PROTECTED]>
http://www.arcs.ac.at/
http://www.researchstudio.at/
http://dme.researchstudio.at/
HG Wien – FN 115980i – ATU14703506
--
Mag. Markus Reis
Austrian Research Centers GmbH - ARC
Research Studios
Studio Digital Memory Engineering
Thurngasse 8/3/20, A-1090 Wien
Mobile: +43 664 825 1106
Tel.: +43-1-585 05 37 - 16
Fax: +43-1-585 37 41
<[EMAIL PROTECTED]>
http://www.arcs.ac.at/
http://www.researchstudio.at/
http://dme.researchstudio.at/
HG Wien – FN 115980i – ATU14703506
--
Mag. Markus Reis
Austrian Research Centers GmbH - ARC
Research Studios
Studio Digital Memory Engineering
Thurngasse 8/3/20, A-1090 Wien
Mobile: +43 664 825 1106
Tel.: +43-1-585 05 37 - 16
Fax: +43-1-585 37 41
<[EMAIL PROTECTED]>
http://www.arcs.ac.at/
http://www.researchstudio.at/
http://dme.researchstudio.at/
HG Wien – FN 115980i – ATU14703506
--
Mag. Markus Reis
Austrian Research Centers GmbH - ARC
Research Studios
Studio Digital Memory Engineering
Thurngasse 8/3/20, A-1090 Wien
Mobile: +43 664 825 1106
Tel.: +43-1-585 05 37 - 16
Fax: +43-1-585 37 41
<[EMAIL PROTECTED]>
http://www.arcs.ac.at/
http://www.researchstudio.at/
http://dme.researchstudio.at/
HG Wien – FN 115980i – ATU14703506