Showing posts with label ftpadapter. Show all posts
Showing posts with label ftpadapter. Show all posts

Friday, June 8, 2012

Oracle DbAdapter, FileAdapter, FTPAdapter automated customization

Put in SVN the Deployment Plan created manually in an environment - if makes no sense to create the Plan.xml programmatically, it's only asking for trouble.

In them, replace the actual environment-dependent values with tokens like ${DOMAIN_NAME}
the tokens are:
tokens=DOMAIN_NAME,FTP_HOST,FTP_PASSWORD,FTP_USER

The JNDI names of all your DataSources will not change from environment to environment, so there is no point in replacing them.

create a adapters.properties file like this:

plan1=/opt/oracle/domains/${DOMAIN_NAME}/shared/apps/dbadapter/plan/DBAdapterPlan.xml
plan2=/opt/oracle/domains/${DOMAIN_NAME}/shared/apps/fileadapter/plan/FileAdapterPlan.xml
plan3=/opt/oracle/domains/${DOMAIN_NAME}/shared/apps/ftpadapter/plan/FTPAdapterPlan.xml

plans=plan1,plan2,plan3

adapter1=/opt/oracle/fmw11_1_1_5/osb/soa/connectors/DbAdapter.rar
adapter2=/opt/oracle/fmw11_1_1_5/osb/soa/connectors/FileAdapter.rar
adapter3=/opt/oracle/fmw11_1_1_5/osb/soa/connectors/FtpAdapter.rar

adapters=adapter1,adapter2,adapter3

username=weblogic
password=welcome1
url=t3://myhost.acme.com:7001

tokens=DOMAIN_NAME,FTP_HOST,FTP_PASSWORD,FTP_USER
DOMAIN_NAME=osbpl1do
FTP_HOST=myfthost.acme.com
FTP_PASSWORD=pippopassword
FTP_USER=pippouser


create a WLST script like this:

#############################################################################
#
# Configure a new environment with the Plans.xml from SVN
# uses adapters.properties file.
#
#############################################################################

from java.io import FileInputStream
from shutil import copyfile
import os, sys
import re

#not used, keep only as a reference
def copyfileobj(fsrc, fdst, length=16*1024):
    """copy data from file-like object fsrc to file-like object fdst"""
    while 1:
        buf = fsrc.read(length)
        if not buf:
            break
        fdst.write(buf)

def copyfileWithTokenSubstitution(filein, fileout, properties):
        input = open(filein)
        output = open(fileout, 'w')
        for s in input:
            rep = s
            for tokenname in properties.get("tokens").split(','):
                rep = rep.replace("${" + tokenname + "}", properties.get(tokenname))
            output.write(rep)
        input.close()
        output.close()
    
#not used, keep only as a reference
def copyfile(src, dst):
    """Copy data from src to dst"""
    fsrc = None
    fdst = None
    try:
        fsrc = open(src, 'rb')
        fdst = open(dst, 'wb')
        copyfileobj(fsrc, fdst)
    finally:
        if fdst:
            fdst.close()
        if fsrc:
            fsrc.close()



    
propertyFileName = 'adapters.properties'    

#loading properties
print 'Loading properties from ', propertyFileName
propInputStream = FileInputStream(propertyFileName)
configProps = Properties()
configProps.load(propInputStream)

domainName = configProps.get('DOMAIN_NAME')

plans=configProps.get("plans")
adapters=configProps.get("adapters")

planArray = []
adapterArray = []

#create needed directories where to put *Plan.xml
for plan in plans.split(','):
    planFullPath = configProps.get(plan).replace("${DOMAIN_NAME}", domainName)
    planArray.append(planFullPath)

#create array of adapters
for adapter in adapters.split(','):
    adapterName = configProps.get(adapter)
    adapterArray.append(adapterName)


#create dir if doesn't exist - fail if unable to create it
for planFullPath in planArray:    
    dirName = os.path.dirname(planFullPath)
    print "creating directory " + dirName
    if not os.path.exists(dirName):
        os.makedirs(dirName)
    
#check for directory existence
for planFullPath in planArray:
    dirName = os.path.dirname(planFullPath)
    print "testing directory " + dirName
    
    if not os.path.exists(dirName):
        message = "directory " + dirName + " does not exist"
        print message
        raise Exception(message)

    

#copy all Plan.xml files to their final destination, with token substitution
for planFullPath in planArray:
    fileName = os.path.basename(planFullPath)
    print "copying " + fileName + " to " + planFullPath  
    copyfileWithTokenSubstitution(fileName, planFullPath, configProps)

#Connect to Admin Server    
connect(configProps.get("username"),configProps.get("password"),configProps.get("url"))

#applying changes to the Adapters
edit()
try:
    for index in range(len(planArray)):
        startEdit()
        plan = planArray[index]
        adapter = adapterArray[index]
        
        adapterType = os.path.basename(adapter).split('.')[0]
        
        print 'Applying plan ' + plan + " to adapter " + adapter + " (adapter type is " + adapterType + ")"
        myPlan = loadApplication(adapter, plan)
        myPlan.save()
        save()
        activate(block='true')
        cd('/AppDeployments/' + adapterType + '/Targets')
        #updateApplication(appName, planPath);
        redeploy(adapterType, plan, targets = cmo.getTargets())
         

except:
    dumpStack()
    stopEdit('y')
    message="unable to finish job"
    raise Exception(message)

disconnect()
print "job finished successfully"



Saturday, May 26, 2012

The FTP MOVE operation with a JCA FTP Adapter

the difference between the case with RNFR-RNTO and the case of COPY/DELETE. The difference is simpls using

UseNativeRenameOperation = "true"
UseFtpRenameOperation = "true"

in the dynamic JCA properties of the Business Service built on top the JCA FTPAdapter


THIS IS THE GOOD CASE, with
UseNativeRenameOperation = "true"
UseFtpRenameOperation = "true"


the MOVE is done with a RNFR-RNTO:

[ INFO] 2012-05-25 23:41:17,664 [myuser] [10.19.10.100] RECEIVED: RNFR /myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982077267PO_FFMW_AVE_1337982077267.xml
[ INFO] 2012-05-25 23:41:17,665 [myuser] [10.19.10.100] SENT: 350 Requested file action pending further information.

[ INFO] 2012-05-25 23:41:17,666 [myuser] [10.19.10.100] RECEIVED: RNTO /myuser/environments/env-0/ave/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982077267PO_FFMW_AVE_1337982077267.xml
[ INFO] 2012-05-25 23:41:17,667 [myuser] [10.19.10.100] File rename from "/myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982077267PO_FFMW_AVE_1337982077267.xml" to "/myuser/environments/env-0/ave/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982077267PO_FFMW_AVE_1337982077267.xml"
[ INFO] 2012-05-25 23:41:17,668 [myuser] [10.19.10.100] SENT: 250 Requested file action okay, file renamed.


THIS IS THE BAD CASE, without using the "UseNative" options: the move is done by RETRIEVING locally the file, COPYING it to destination and DELETING the remote source:


[ INFO] 2012-05-25 23:47:17,806 [myuser] [10.19.10.100] RECEIVED: RETR /myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml
[ INFO] 2012-05-25 23:47:17,807 [myuser] [10.19.10.100] File downloaded /myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml
[ WARN] 2012-05-25 23:47:17,808 [myuser] [10.19.10.100] Releasing unreserved passive port: 54862
[ INFO] 2012-05-25 23:47:17,808 [myuser] [10.19.10.100] SENT: 150 File status okay; about to open data connection.

[ INFO] 2012-05-25 23:47:17,808 [myuser] [10.19.10.100] SENT: 226 Transfer complete.

[ INFO] 2012-05-25 23:47:17,847 [myuser] [10.19.10.100] RECEIVED: PWD
[ INFO] 2012-05-25 23:47:17,848 [myuser] [10.19.10.100] SENT: 257 "/" is current directory.

[ INFO] 2012-05-25 23:47:17,848 [myuser] [10.19.10.100] RECEIVED: TYPE I
[ INFO] 2012-05-25 23:47:17,849 [myuser] [10.19.10.100] SENT: 200 Command TYPE okay.

[ INFO] 2012-05-25 23:47:17,849 [myuser] [10.19.10.100] RECEIVED: PWD
[ INFO] 2012-05-25 23:47:17,850 [myuser] [10.19.10.100] SENT: 257 "/" is current directory.

[ INFO] 2012-05-25 23:47:17,850 [myuser] [10.19.10.100] RECEIVED: CWD /myuser/environments/env-0/ave
[ INFO] 2012-05-25 23:47:17,851 [myuser] [10.19.10.100] SENT: 250 Directory changed to /myuser/environments/env-0/ave

[ INFO] 2012-05-25 23:47:17,851 [myuser] [10.19.10.100] RECEIVED: PASV
[ INFO] 2012-05-25 23:47:17,852 [myuser] [10.19.10.100] SENT: 227 Entering Passive Mode (10,56,5,192,234,152)

[ INFO] 2012-05-25 23:47:17,852 [myuser] [10.19.10.100] RECEIVED: STOR POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml
[ INFO] 2012-05-25 23:47:17,853 [myuser] [10.19.10.100] File uploaded /myuser/environments/env-0/ave/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml
[ WARN] 2012-05-25 23:47:17,853 [myuser] [10.19.10.100] Releasing unreserved passive port: 60056
[ INFO] 2012-05-25 23:47:17,853 [myuser] [10.19.10.100] SENT: 150 File status okay; about to open data connection.

[ INFO] 2012-05-25 23:47:17,854 [myuser] [10.19.10.100] SENT: 226 Transfer complete.

[ INFO] 2012-05-25 23:47:17,894 [myuser] [10.19.10.100] RECEIVED: CWD /
[ INFO] 2012-05-25 23:47:17,895 [myuser] [10.19.10.100] SENT: 250 Directory changed to /

[ INFO] 2012-05-25 23:47:17,896 [myuser] [10.19.10.100] RECEIVED: PWD
[ INFO] 2012-05-25 23:47:17,897 [myuser] [10.19.10.100] SENT: 257 "/" is current directory.

[ INFO] 2012-05-25 23:47:17,898 [myuser] [10.19.10.100] RECEIVED: DELE /myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml
[ INFO] 2012-05-25 23:47:17,899 [myuser] [10.19.10.100] File delete : myuser - /myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml
[ INFO] 2012-05-25 23:47:17,899 [myuser] [10.19.10.100] SENT: 250 Requested file action okay, deleted /myuser/environments/env-0/ave/tmp/POCREATE^PuO20111212_164122_1640.txt^AVE^1337982437334PO_FFMW_AVE_1337982437334.xml.





note: those options are totally undocumented

you need to add this

<jca:dynamic-endpoint-properties>
        <jca:endpoint-property>
          <jca:name>UseNativeRenameOperation</jca:name>
          <jca:value>true</jca:value>
        </jca:endpoint-property>
        <jca:endpoint-property>
          <jca:name>UseFtpRenameOperation</jca:name>
          <jca:value>true</jca:value>
        </jca:endpoint-property>
      </jca:dynamic-endpoint-properties>

in your BS at the end of the tran:provider-specific section


These events are visible also in the WLS logs if you enable java:alsb-jca-framework-adapter-debug in alsbdebug.xml

Tuesday, May 22, 2012

The IO operation failed. BINDING.JCA-11096

We are using a JCA FTPAdapter,and occasionally, under load, the FTPMove operation fails:

Unable to delete file '/messages/somefile.xml'; FTP command DELE returned unexpected reply code : 550



WSIF JCA Execute of operation ''FTPMove'' failed due to: The IO operation failed.
The IO operation failed.
The "OPER[NOOP][S->R,T->R]" IO operation for "/messages/somefile.xml" failed.
; nested exception is: 
 BINDING.JCA-11096
The IO operation failed.
The IO operation failed',null,null,null);



Looking in the oracle.tip.adapter.ftp.outbound.FTPIoOperation, I find out that "S->R,T->R" means "Source=Remote, Target=Remote - in fact we are moving files on the remote destination only.


and I see in the logs:

Error deleting file from FTP Server.
Error deleting file from FTP Server.
Unable to delete file from server.
Please ensure whether the remote file has delete permission.

        at oracle.tip.adapter.ftp.FTPClient.deleteFile(FTPClient.java:1362)
        at oracle.tip.adapter.ftp.FTPAgent.deleteFile(FTPAgent.java:736)
        at oracle.tip.adapter.ftp.outbound.FTPIoOperation.deleteFile(FTPIoOperation.java:188)
        at oracle.tip.adapter.ftp.outbound.FTPIoOperation.ioOnly(FTPIoOperation.java:174)


and in this case the code executed is:


if(!alreadyMoved && success && move)
try
{
deleteFile(fs.getSourceAgent(), spec, fInfo);
}
catch(Exception e)
{
throw new FileRetriableResourceException(11096, new Object[] {
(new StringBuilder()).append("OPER[NOOP][").append(mode).append("]").toString(), (new StringBuilder()).append(targetDir).append("/").append(targetFile).toString()
}, e);
}





Error "Please ensure whether the remote file has delete permission" is 11434


The delete is actually done in oracle.tip.adapter.ftp.FTPClient:

public boolean deleteFile(FTPManagedConnection managedConnection, String file)
        throws IOException, ResourceException
    {
        Socket controlSocket = managedConnection.getControlSocket();
        String replyStr = dele(controlSocket, file);
        int rc = getReplyCode(replyStr, m_ftpDesc.ftpHost);
        log((new StringBuilder()).append("FTPClient.deleteFile(): ").append(replyStr).toString(), 102);
        if(!m_ftpReplyValidator.isValidDELEReturnCode(rc))
        {
            log((new StringBuilder()).append("Unable to delete file '").append(file).append("'; ").append("FTP command DELE returned unexpected reply code : ").append(rc).toString(), 100);
            FileResourceException frex = new FileResourceException(11434);
            frex.setEISErrorCode(String.valueOf(rc));
            frex.setEISErrorMessage(replyStr);
            throw frex;
        } else
        {
            return true;
        }
    }

in oracle.tip.adapter.ftp.FTPReply I find out that:

public static final int FILE_UNAVAILABLE = 550;



still no clue on what goes wrong...


I understand that there is a FTP RNTO mode, if you want to enable, specify the JCA activation property UseFtpRenameOperation=true or UseNativeRenameOperation=true.
This will entail using a move() operation rather than a copy followed by a delete (you have to look at FTPIoOperation.ioOnly() method).


PS I discovered after a lot of pain that we were generating twice the same filename on the destination.... not a good idea...

Tuesday, February 21, 2012

validateControlSocket

We are getting some weird socket timeout problems
on FTPClient and FtpDescriptor there is a JCA property
control.read.timeout
by default it's 15000
and also a
control.read.error_on_timeout
by default it's true

you can set it to false to get rid of the problem


RETR command: http://cr.yp.to/ftp/retr.html

A RETR request asks the server to send the contents of a file over the data connection already established by the client.


####<Feb 21, 2012 4:10:29 PM CET> <Debug> <AlsbJcaFrameworkAdapter> <hqchnesoa102> <osbdv2ms1> <[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <7f9b72b69446518a:-3e7d8906:1359f3f0c67:-8000-0000000000000a3b> <1329837029661> <BEA-000000> <FTP Command: RETR, reply:
150 Opening data connection for /acme/environments/env-0/ave/tmp/ITEM_X_ACME_AVE_1329837028553.xml (408 bytes).

>

####<Feb 21, 2012 4:10:29 PM CET> <Debug> <AlsbJcaFrameworkAdapter> <hqchnesoa102> <osbdv2ms1> <[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <7f9b72b69446518a:-3e7d8906:1359f3f0c67:-8000-0000000000000a3b> <1329837029661> <BEA-000000> <shortCircuit==>true>

####<Feb 21, 2012 4:10:29 PM CET> <Debug> <AlsbJcaFrameworkAdapter> <hqchnesoa102> <osbdv2ms1> <[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <7f9b72b69446518a:-3e7d8906:1359f3f0c67:-8000-0000000000000a3b> <1329837029661> <BEA-000000> <validateControlSocket::Control socket being read by [[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)']>

####<Feb 21, 2012 4:10:44 PM CET> <Debug> <AlsbJcaFrameworkAdapter> <hqchnesoa102> <osbdv2ms1> <[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <7f9b72b69446518a:-3e7d8906:1359f3f0c67:-8000-0000000000000a3b> <1329837044661> <BEA-000000> <Timed out in [15000] msecs>

####<Feb 21, 2012 4:10:44 PM CET> <Debug> <AlsbJcaFrameworkAdapter> <hqchnesoa102> <osbdv2ms1> <[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <7f9b72b69446518a:-3e7d8906:1359f3f0c67:-8000-0000000000000a3b> <1329837044662> <BEA-000000> <Exception caught while reading control socket
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at oracle.tip.adapter.ftp.FTPClient$BufferedTimedReader.readLine(FTPClient.java:2385)
at oracle.tip.adapter.ftp.FTPClient.validateControlSocket(FTPClient.java:931)
at oracle.tip.adapter.ftp.FTPClient.getBinaryFileAsStream(FTPClient.java:1225)
at oracle.tip.adapter.ftp.FTPAgent.getBinaryFileAsStream(FTPAgent.java:654)
at oracle.tip.adapter.ftp.FTPAgent.getContentAsStream(FTPAgent.java:700)
at oracle.tip.adapter.ftp.inbound.FTPSource.getContents(FTPSource.java:987)
at oracle.tip.adapter.ftp.inbound.FTPSource.getFileFromSource(FTPSource.java:912)
at oracle.tip.adapter.ftp.outbound.FTPIoOperation.ioOnly(FTPIoOperation.java:119)
at oracle.tip.adapter.ftp.outbound.FTPIoOperation$2.perform(FTPIoOperation.java:844)
at oracle.tip.adapter.ftp.outbound.FTPInteraction.executeFTPIo(FTPInteraction.java:287)
at oracle.tip.adapter.ftp.outbound.FTPInteraction.execute(FTPInteraction.java:245)
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.performOperation(WSIFOperation_JCA.java:529)
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.executeOperation(WSIFOperation_JCA.java:353)
at oracle.tip.adapter.sa.impl.fw.wsif.jca.WSIFOperation_JCA.executeRequestResponseOperation(WSIFOperation_JCA.java:312)
at oracle.tip.adapter.sa.impl.JCABindingReferenceImpl.invokeWsifProvider(JCABindingReferenceImpl.java:350)
at oracle.tip.adapter.sa.impl.JCABindingReferenceImpl.request(JCABindingReferenceImpl.java:253)
at com.bea.wli.sb.transports.jca.binding.JCATransportOutboundOperationBindingServiceImpl.invoke(JCATransportOutboundOperationBindingServiceImpl.java:150)
at com.bea.wli.sb.transports.jca.JCATransportEndpoint.sendRequestResponse(JCATransportEndpoint.java:209)
at com.bea.wli.sb.transports.jca.JCATransportEndpoint.send(JCATransportEndpoint.java:170)
at com.bea.wli.sb.transports.jca.JCATransportProvider.sendMessageAsync(JCATransportProvider.java:598)
at sun.reflect.GeneratedMethodAccessor1154.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.bea.wli.sb.transports.Util$1.invoke(Util.java:83)
at $Proxy128.sendMessageAsync(Unknown Source)
at com.bea.wli.sb.transports.LoadBalanceFailoverListener.sendMessageAsync(LoadBalanceFailoverListener.java:148)
at com.bea.wli.sb.transports.LoadBalanceFailoverListener.sendMessageToServiceAsync(LoadBalanceFailoverListener.java:603)
at com.bea.wli.sb.transports.LoadBalanceFailoverListener.sendMessageToService(LoadBalanceFailoverListener.java:538)




still chasing what is at the origin of the problem...

Saturday, December 3, 2011

OSB move remote file with JCA FTP Adapter

A common requirement is to add a bit of transactional behavior in FTP operations:

Example:

- FTP file1 to remote dir /path/to/myfiles
- FTP file2 to remote dir /path/to/myfiles
- tell remote system that he can start processing file1 and file2

If FTP of file2 fails, you don't want to leave file1 hanging around.
So you should add a fastidious compensation action in the Error Handler of "FTP file2" to undo the "FTP file1" operation.
Also, fastidiously the file could be picked up by remote system before I end transferring it (it should not happen, I guess it depends on the FTP server implementation, it's just one extra concern I have).

This clearly sucks.

Luckily the Oracle JCA FTP Adapter supports moving remote files.

The FTPMove operation with Type="MOVE" has been successfully tested, using Transport Headers to pass the "file name from" and "to" parameters to the JCA Adapter.

Interestingly enough, you can also COPY and DELETE files remotely.

So our flow will be:

- FTP file1 to remote dir /path/to/myfilestemp
- FTP file2 to remote dir /path/to/myfilestemp
- FTP move file1 to /path/to/myfiles
- FTP move file2 to /path/to/myfiles


Ok you will say "what if - ##FTP move file2 to /path/to/myfiles## fails?".
Well, I guess that can happen....

Wednesday, November 23, 2011

Error FTPing with JCA FTP Adapter


BEA-381971


Invoke JCA outbound service failed with connection error, exception: com.bea.wli.sb.transports.jca.JCATransportException: oracle.tip.adapter.sa.api.JCABindingException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/WSDL/ACME_PurchaseOrder/PV_FtpToACME [ Put_ptt::Put(body) ] - WSIF JCA Execute of operation 'Put' failed due to: Error in establishing connection to FTP Server.
Error in establishing connection to FTP Server.
Unable to establish connection to server.
; nested exception is:
BINDING.JCA-11438
Error in establishing connection to FTP Server.
Error in establishing connection to FTP Server.
Unable to establish connection to server.
Please ensure hostname and port specified to login to the server is correct.



The FTP Put is done in a Local Transaction:

in the log you will find:

JCA_FRAMEWORK_AND_ADAPTER Starting JCA LocalTransaction

and when the error occurs:

JCA_FRAMEWORK_AND_ADAPTER Rolling back JCA LocalTransaction

For the NoTransConnEventListener of pool 'eis/Ftp/ACMEFtpAdapter' CONNECTION_CLOSED event received

servicebus:/WSDL/ACME_PurchaseOrder/PV_FtpToACME [ Put_ptt::Put(body) ] - Marking this exception as Locally Retryable

WSIFCache: Closing CCI Connection

In fact the JCA Adapter for File and FTP do not support XA Transaction, but only Local Transactions.


The message is retried the number of times determined by the Business Service generated on top of the JCA Adapter:

Transport Configuration
Protocol jca
Load Balancing Algorithm round-robin
Endpoint URI
jca://eis/Ftp/ACMEFtpAdapter
Retry Count 2
Retry Iteration Interval 30
Retry Application Errors No

So in this case the message will be tried 3 times (2 retries) before erroring out. The local transaction only is retried, while the global transaction is still active. This makes the global transaction last 60 seconds.

Be aware that these local transactions are executed as part of the Proxy Service transaction: if you define 10 retries at 1 minute interval, your global transaction will be open for 10 minutes. So this is not a viable solution.

This is what you will see at the end of the TX:

<BEA-010213> <Message-Driven EJB: RequestEJB-7263521924761754948--49bf0c34.133cb4ae47d.-7fe0's transaction was rolled back. The transaction details are: Xid=BEA1-01DB458350C2A589D5FB(10150583),Status=Rolled back. [Reason=weblogic.transaction.internal.AppSetRollbackOnlyException: setRollbackOnly called on transaction],numRepliesOwedMe=0,numRepliesOwedOthers=0,seconds since begin=306,seconds left=60,XAServerResourceInfo[WLStore_prod_domain_FileStore_auto_1]=(ServerResourceInfo[WLStore_prod_domain_FileStore_auto_1]=(state=rolledback,assigned=osb_server1),xar=WLStore_prod_domain_FileStore_auto_121108363,re-Registered = false),SCInfo[prod_domain+osb_server1]=(state=rolledback),OwnerTransactionManager=ServerTM[ServerCoordinatorDescriptor=(CoordinatorURL=osb_server1+pierrepc:7011+prod_domain+t3+, XAResources={eis/tibjms/Topic, WLStore_prod_domain_FileStore_auto_1, eis/aqjms/Queue, eis/fioranomq/Topic, eis/wls/Queue, eis/tibjms/Queue, eis/activemq/Queue, WLStore_prod_domain_ACMEFileStore1, eis/pramati/Queue, WLStore_prod_domain__WLS_osb_server1, eis/tibjmsDirect/Queue, eis/Apps/Apps, eis/jbossmq/Queue, eis/sunmq/Queue, WSATGatewayRM_osb_server1_prod_domain, eis/aqjms/Topic, eis/tibjmsDirect/Topic, eis/wls/Topic, eis/AQ/aqSample, wlsbjmsrpDataSource_prod_domain, eis/webspheremq/Queue, WLStore_prod_domain_WseeFileStore_auto_1},NonXAResources={})],CoordinatorURL=osb_server1+pierrepc:7011+prod_domain+t3+).>


Go to the Server/MOnitoring/JTA/Transaction tab and you will see the transaction open for the entire duration of the retries. The transactionId is also traced in the logs.

We were consuming the message from a JMS queue, and redirecting on error to an ErrorQueue.

Friday, November 18, 2011

Move operation in JCA FTP Adapter

the UseNativeRenameOperation seems promising to do a Move (RNFR/RNTO) operation:

http://download.oracle.com/docs/cd/E12839_01/integration.1111/e10231/adptr_file.htm


but I haven't tested it yet...

Monday, November 14, 2011

opaq:opaqueElement and base64Binary

If you want to write binary data to a FTP in OSB (or simply you want to avoid any nXSD transformation in your XML), you have the option of using

opaq:opaqueElement

You should in this case base64-encode your payload.
The bad news is that in Xquery 1.0 there is not a function to base64encode

You can do a Java Callout or a Custom XPath to a Java function.

There are plenty of BASE64Encoder classes around... from the BEA WLI framework, from Sun, from Apache....

In fact, Sun implementation
http://stackoverflow.com/questions/5549464/import-sun-misc-base64encoder-got-error-in-eclipse is not really an option.

We have identified the Apache Commons base64 encoder - in alternative to Sun implementation, since Sun (Oracle) itself recommends NOT to use sun packages http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html - as the most commonly used encoder.


So, use this http://commons.apache.org/codec/ commons-codec-1.4.jar

Thursday, November 10, 2011

JCATransport:381987 in JCA FTP Adapter

I have created a FTP Adapter in JDeveloper 11.1.1.5 and imported in OSB.

When I activate, I get this beautiful conflict


[JCATransport:381987]An error occured while validating JCA transport endpoint. JNDI lookup with URL: jca://eis/ftp/FtpAdapter failed. Missing JNDI configuration such as undeployed or misconfigured JCA Adapter RAR or connection factory.



Well, embarrassingly enough it turns out that the actual JNDI Binding name is eis/Ftp/FtpAdapter and not eis/ftp/FtpAdapter (upper case F) as proposed by

I wonder how such a blunder could take place in JDeveloper...