- Index
- » Saddle Forum
- » User
- » Database poller to CSV file writer -...
Database poller to CSV file writer - problems reading and writing data
Database poller to CSV file writer - problems reading and writing data
I have a very simple workflow that reads a database periodically and writes out all rows to a file.
I am using Saddle NIGHTLY 20120327 and mule 3.2.1 build 23380.
Having the following problems:
* The DB retrieval doesn't seem to scroll through the result set. The output into the file is only the 1st row but the correct number of times (equal to # rows in table).
* Output to the file works as long as the outbound Message To MixedString transformer is set to "Provide as XML". An exception is thrown if the checkbox is unchecked. I am assuming I need to specify some field delimiters for the CSV output but I have no idea where to do that.
Here is what my table looks like in postgres. Id is a serial column and the other 3 fields of interest (facility,dos,patacctnum) are varchar.
Code:
db_dd=> select * from adt_in;
id | facility_id | facility | source | dos | patacctnum | msgtype | active | payload | processed | created
-------+-------------+-----------------+--------+----------+------------+---------+--------+---------+-----------+-------------------------------
21633 | | test_facility_3 | | 20120329 | 2345678 | | 1 | | | 2012-03-28 17:04:20.647764-07
21634 | | test_facility_4 | | 20120321 | 3456789 | | 1 | | | 2012-03-28 17:31:00.470786-07
(2 rows)
I am attaching my project.zip.
project.zip
Re: Database poller to CSV file writer - problems reading and writing data
Hi Jacek,
Thanks for reporting your problems.
Nothing's bad here, I reproduced it on a similar MySql DB and now got it working.
First, the easiest: Message To MixedString transformer.
You're right, you have to specify delimiters. The template you use on this transformer is PatientOut, so let's have a look at it. If you click on the root node (PatientOut), on the right you'll see properties applying to the whole template. You have to look for those called "Default field delimiter level 1 (and 2)".
Level 1 refers to ResultSet (which is, I suppose, a line in the desired file) so you set the deliniter to \n, \r\n or the tags <lf> or <wincr> (look at the documentation that appears when you click on the property)
Level 2 refers to whatever is inside level 1, that means the separator for each field in a line. I picked the pipe symbol here, but you can type anything you want.
Now, let's have a look at the MapInToOut mapping.
When you printed the number of rows
Code:
getDbReader().getNumberOfInstances()
returns the number of root nodes, which is 1. If you replace it with
Code:
getDbReader().getField("/DdPatient/ResultSet").getNumberOfInstances()
you get the right number of rows, as each row is stored in a ResultSet.
In a for loop, you should directly used the variable in for(), and retrive the value like this
Code:
String id = currentPat.getChildValueAsString("id")
To write in the output template, proceed like this:
Code:
line.setChildValue("id", id);
Finally, unless you have a triggered endpoint in you mapping, don't use the dispatchMessage() method, but return your out template.
Attahced in the MapInToOut java file that works for me: MapInToOut.java. You'll notice that it simplifies the code as well.
I hope this helps. If you have any other question, don't hesitate to post.
Can I ask you in which context you're using Saddle ? For a lab, hospital, ... ? We're always interested to know who finds Saddle useful and for what kind of applications. Thanks!
Re: Database poller to CSV file writer - problems reading and writing data
Thank you very much for your prompt and accurate assistance. Your changes work beautifully.
dispatchMessage(getOutFile()) works just the same as the return getOutFile() -- Is there a potential problem with dispatchMessage in my case?
My application is EMR integration with other devices at physician clinics. I'll write more details as the project progresses.
Next up for me is to replace the file outbound endpoint with an HL7 endpoint. Do you have any hints on triggering out HL7 messages for each row in the database and receiving and verifying ACKs?
Thank you!
Jacek
Re: Database poller to CSV file writer - problems reading and writing data
Hi Jacek,
jacek wrote:
dispatchMessage(getOutFile()) works just the same as the return getOutFile() -- Is there a potential problem with dispatchMessage in my case?
No, not in your current configuration but..
jacek wrote:
Next up for me is to replace the file outbound endpoint with an HL7 endpoint. Do you have any hints on triggering out HL7 messages for each row in the database and receiving and verifying ACKs?
... that's exactly where you will start to realize the difference:
While calling return getOutFile() will end the mapping when you send the first row to the HL7 endpoint, you are able to continue to fill your HL7 template with the data from the subsequent row and call dispatchMessage(getOutFile()) for each row you filled in. That way, for each row a new instance of OutFile will be sent to your HL7 Endpoint.
An example of how to receive and handle an ACK/NAK can be found in the HL7 tutorial, that you can find under "Tutorials" in the download section.
regards,
Ortwin
- Ortwin
- 115 Posts
Re: Database poller to CSV file writer - problems reading and writing data
OK, Thank you for the response. I'll take a close look at the tutorial.
For now, I'm trying to just dispatch the HL7 outbound on port 6000. Reading the DB fine, the mapper seems to do the trick but the dispatch blows up in the HL7 connector (one-way, since request-response is not working - probably because I don't have an ACK reader configured).
Here is the mule log:
Code:
org.mule.api.transport.DispatchException: Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=hl7://localhost:6000, connector=Hl7Connector
{
name=HL7Connector
lifecycle=start
this=95d0a50
numberOfConcurrentTransactedReceivers=4
createMultipleTransactedReceivers=true
connected=true
supportedProtocols=[hl7]
serviceOverrides=<none>
}
, name='OutboundHL7', mep=ONE_WAY, properties={}, transactionConfig=Transaction{factory=null, action=INDIFFERENT, timeout=0}, deleteUnacceptedMessages=false, initialState=started, responseTimeout=10000, endpointEncoding=UTF-8, disableTransportTransformer=false}. Message payload is of type: byte[]
at org.mule.transport.AbstractConnector$DispatcherMessageProcessor.process(AbstractConnector.java:2567)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.processor.AsyncInterceptingMessageProcessor.process(AsyncInterceptingMessageProcessor.java:90)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.doProcess(InterceptingChainLifecycleWrapper.java:56)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.process(InterceptingChainLifecycleWrapper.java:87)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.endpoint.outbound.OutboundResponsePropertiesMessageProcessor.process(OutboundResponsePropertiesMessageProcessor.java:39)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.processor.TransactionalInterceptingMessageProcessor$1.doInTransaction(TransactionalInterceptingMessageProcessor.java:49)
at org.mule.processor.TransactionalInterceptingMessageProcessor$1.doInTransaction(TransactionalInterceptingMessageProcessor.java:46)
at org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:45)
at org.mule.processor.TransactionalInterceptingMessageProcessor.process(TransactionalInterceptingMessageProcessor.java:55)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.processor.AbstractFilteringMessageProcessor.process(AbstractFilteringMessageProcessor.java:44)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.doProcess(InterceptingChainLifecycleWrapper.java:56)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.process(InterceptingChainLifecycleWrapper.java:87)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.doProcess(InterceptingChainLifecycleWrapper.java:56)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.process(InterceptingChainLifecycleWrapper.java:87)
at org.mule.endpoint.DefaultOutboundEndpoint.process(DefaultOutboundEndpoint.java:95)
at org.mule.routing.outbound.AbstractOutboundRouter.sendRequestEvent(AbstractOutboundRouter.java:461)
at org.mule.routing.outbound.AbstractOutboundRouter.sendRequest(AbstractOutboundRouter.java:167)
at org.mule.routing.outbound.FilteringOutboundRouter.route(FilteringOutboundRouter.java)
at org.mule.routing.outbound.OutboundPassThroughRouter.route(OutboundPassThroughRouter.java:71)
at org.mule.routing.outbound.AbstractOutboundRouter$1.doInTransaction(AbstractOutboundRouter.java:102)
at org.mule.routing.outbound.AbstractOutboundRouter$1.doInTransaction(AbstractOutboundRouter.java:99)
at org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:45)
at org.mule.routing.outbound.AbstractOutboundRouter.process(AbstractOutboundRouter.java:107)
at org.mule.routing.outbound.DefaultOutboundRouterCollection.process(DefaultOutboundRouterCollection.java:103)
at org.mule.DefaultMuleEventContext.dispatchEvent(DefaultMuleEventContext.java:495)
at MapInToHL7OutBase.dispatchMessage(MapInToHL7OutBase.java:113)
at MapInToHL7OutBase.dispatchMessage(MapInToHL7OutBase.java:94)
at MapInToHL7Out.work(MapInToHL7Out.java:25)
at MapInToHL7OutBase.onCall(MapInToHL7OutBase.java:483)
at org.mule.model.resolvers.CallableEntryPointResolver.invoke(CallableEntryPointResolver.java:50)
at org.mule.model.resolvers.DefaultEntryPointResolverSet.invoke(DefaultEntryPointResolverSet.java:39)
at org.mule.component.DefaultComponentLifecycleAdapter.invoke(DefaultComponentLifecycleAdapter.java:350)
at org.mule.component.AbstractJavaComponent.invokeComponentInstance(AbstractJavaComponent.java:86)
at org.mule.component.AbstractJavaComponent.doInvoke(AbstractJavaComponent.java:77)
at org.mule.component.AbstractComponent.invokeInternal(AbstractComponent.java:126)
at org.mule.component.AbstractComponent.access$000(AbstractComponent.java:61)
at org.mule.component.AbstractComponent$1$1.process(AbstractComponent.java:242)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.doProcess(InterceptingChainLifecycleWrapper.java:56)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.process(InterceptingChainLifecycleWrapper.java:87)
at org.mule.component.AbstractComponent.process(AbstractComponent.java:160)
at org.mule.service.processor.ServiceInternalMessageProcessor.process(ServiceInternalMessageProcessor.java:43)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.interceptor.AbstractEnvelopeInterceptor.process(AbstractEnvelopeInterceptor.java:55)
at org.mule.processor.AsyncInterceptingMessageProcessor.processNextTimed(AsyncInterceptingMessageProcessor.java:111)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker.doRun(AsyncInterceptingMessageProcessor.java:158)
at org.mule.work.AbstractMuleEventWork.run(AbstractMuleEventWork.java:43)
at org.mule.work
.WorkerContext.run(WorkerContext.java:310)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Caused by: org.mule.api.transport.ConnectorException: Connector that caused exception is: null. Connector that caused exception is: Hl7Connector
{
name=HL7Connector
lifecycle=start
this=95d0a50
numberOfConcurrentTransactedReceivers=4
createMultipleTransactedReceivers=true
connected=true
supportedProtocols=[hl7]
serviceOverrides=<none>
}
at org.mule.transport.AbstractConnector.getDispatcher(AbstractConnector.java:1056)
at org.mule.transport.AbstractConnector.access$600(AbstractConnector.java:130)
at org.mule.transport.AbstractConnector$DispatcherMessageProcessor.process(AbstractConnector.java:2547)
... 69 more
Caused by: java.lang.NullPointerException
at org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:1179)
at org.mule.transport.DefaultConfigurableKeyedObjectPool.borrowObject(DefaultConfigurableKeyedObjectPool.java:40)
at org.mule.transport.AbstractConnector.getDispatcher(AbstractConnector.java:1044)
... 71 more
Attached is the updated project (which includes the working db-file workflow and the nonworking db-hl7 workflow).
Thank you
Jacek
project.zip
Re: Database poller to CSV file writer - problems reading and writing data
jacek wrote:
probably because I don't have an ACK reader configured).
Well, in this case mule will simply return the ACK to the caller, meaning the database endpoint. Perhaps that's where the problem is, I will investigate it further and tell you about my findings.
Best regards,
Matthias
- mkutscheid
- 309 Posts
Re: Database poller to CSV file writer - problems reading and writing data
Hi Jaz,
I just rebuilt your configuration on my machine and found a small bug in the message lib that prevented incomplete HL7 messages from being sent out correctly. Could you please try it again with the last nightly build (that I just started)? It will contain the bugfix and might perhaps solve your problem.
If it does not please attach the full mule log and application log files, because I think the error might be somewhere else than in the stack trace that you pasted here.
Also the Request-response somehow works for me, so it would be good to have more information on what's going on in your mule installation.
Long story short: please add the full mule and app logs to your posts by simply attaching the files and giving them a name with some timestamp, because otherwise the forum system will simply overwrite the files once you upload new ones and the history will be a bit messed up.
Best regards,
Matthias
- mkutscheid
- 309 Posts
Re: Database poller to CSV file writer - problems reading and writing data
Matthias,
I downloaded the 20120330 build and I'm seeing the same problem. No attempt at connection to port 6000.
Failed to route event:
Code:
**********************************************************************
* poller * DEPLOYED *
**********************************************************************
INFO 2012-03-30 11:48:57,354 [WrapperListener_start_runner] org.mule.module.launcher.DeploymentService:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Mule is up and kicking (every 5000ms) +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mar 30, 2012 11:48:58 AM MapInToHL7Out work
SEVERE: null
org.mule.api.transport.DispatchException: Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=hl7://localhost:6000, connector=Hl7Connector
{
name=HL7Connector
lifecycle=start
this=35ad093c
numberOfConcurrentTransactedReceivers=4
createMultipleTransactedReceivers=true
connected=true
supportedProtocols=[hl7]
serviceOverrides=<none>
}
, name='OutboundHL7', mep=ONE_WAY, properties={}, transactionConfig=Transaction{factory=null, action=INDIFFERENT, timeout=0}, deleteUnacceptedMessages=false, initialState=started, responseTimeout=10000, endpointEncoding=UTF-8, disableTransportTransformer=false}. Message payload is of type: byte[]
Attaching the project.zip, mule.log and app.log.
Thank you very much for your assistance.
Jacek
poller-20120330-01.zip
mule-20120330-01.log
mule-app-poller-20120330-01.log
Re: Database poller to CSV file writer - problems reading and writing data
Hi Jaz,
could you please check whether you have the mule hl7 connector placed somewhere in your mule folder? As far as I know they do not ship it automatically, but if you downloaded it manually and put it into your mule please remove it. In our test we found it not working properly and it might interfere with our connector as it uses the same protocol.
I'm currently having a look at the files you posted and will try to resolve the problem today. I will keep you updated as soon as there's something new.
P.S.: I just had a look at your files and found no difference to mine. Could you please try to download and extract a clean mule instance to your harddrive and run the project again with it? You simply have to change Saddle's mule directory by right clicking the project, selecting properties and then set the path to the new mule installation.
I even tried it on a Mac here and found out that mule seems to have problems in running natively on it and thus falls back to some other way of startup. Could you try to copy the deployed application (poller) to another system, linux or windows, and run it there?
Best regards,
Matthias
- mkutscheid
- 309 Posts
Re: Database poller to CSV file writer - problems reading and writing data
Matthias,
I found and removed lib/mule/mule-transport-mllp-hl7-1.0.jar from mule.
It looks like it's transmitting HL7 now! Fantastic!
I'll write later today after I am able to do more testing - on to populating the HL7 and trying to receive the ACK back.
Thanks a million!
Jacek
Re: Database poller to CSV file writer - problems reading and writing data
I have been looking at the HL7 Tutorial. It's not quite applicable to what I'm doing.
There is ACK generation on an inbound endpoint nothing that accepts an ACK via an outbound endpoint.
The Tutorials don't load correctly in saddle nightly 20120330. Double-click on the workflows generates errors.
Any hints would be appreciated. I assume I'll need to create an ACKToMessage transformer that is fed by my outbound endpoint and also feeds back to the mapping.
I need to be able to read the ACK (or NAK) and then decide whether or not to resend the message or put it into some kind of error queue for later "re-injection".
Re: Database poller to CSV file writer - problems reading and writing data
jaz wrote:
The Tutorials don't load correctly in saddle nightly 20120330. Double-click on the workflows generates errors.
We figured this out just yesterday, too and fixed the issue. please download the tutorial files form the nightly builds page and a current Saddle nightly build to have it fixed for you.
In general, if something like this happens always try the latest nightly builds.
Concerning your problem you should have a look at the FullyEditableBidirectionalCommunication workflow. This one sends something out to an HL7 outbound endpoint and later reads the result (so, an ACk or NAK message) from there and passes it on to a second mapping.
Best regards,
Matthias
- mkutscheid
- 309 Posts
Re: Database poller to CSV file writer - problems reading and writing data
Hi Jaz,
I just had a look at your post yesterday and tried a few things with Mule to solve this part of your problem:
jaz wrote:
I need to be able to read the ACK (or NAK) and then decide whether or not to resend the message or put it into some kind of error queue for later "re-injection".
For this to work you will either have to trick mule into sending things out of your mapping directly (which is really not as handy as it sounds as it involves some configuration steps) if you want to stick to services as a configuration model.
However if you would switch to flows there might be a better solution for you. Mule provides a configuration element called "until successful" which tries to resend a message as long as certain criteria are not met. It also provides a way to collect messages that keep failing for a set amount of retries.
However the downside with this is: I do not have much experience in using this configuration element and Saddle might not fully support it currently.
Is your problem still persisting and are you still trying with Saddle? If so I would try to create a solution for you as I think it is a quite common problem when handling HL7 messages.
Best regards,
Matthias
- mkutscheid
- 309 Posts
Re: Database poller to CSV file writer - problems reading and writing data
I have not been successful yet. I would like to work through it with you to see how we can get the queuing and retransmission to work. If retransmission does not work, then the message needs to be put on an error queue for review and resending later.
Re: Database poller to CSV file writer - problems reading and writing data
Hi Jaz,
If nothing goes wrong I think I will be able to start with the development today. My current idea is a flow based configuration including an "until successful" router which checks some value in the response to the sent HL7 message. However this includes writing an expression parser for Saddle (Field based) messages to allow the until successful to check the messages.
If this does not work or if you need more sophisticated checks in the message I would try an approach with multiple flows, one for retrieving the data from the database and one for sending and checking the result. The second flow will then either try to resend the original message by referencing to itself or send it to an error queue for other processing.
These are my ideas, but they will probably include some enhancements in Saddle. I will see what I can do, if you find something out please let me know here. Also, if you could describe what you want to achieve in the end in more detail I could probably take this into account.
Best regards,
Matthias
- mkutscheid
- 309 Posts
Re: Database poller to CSV file writer - problems reading and writing data
HI Jaz,
I attached the first try of a solution. It allows only basic checking using groovy, but it does the trick for trying to redeliver the message.
In this example I simply check whether the returned ACK says it accepts the message or not and try to redeliver it if the server rejects it.
Have a look at the configuration and try to understand the basics, I will then have a look at a more complicated approach for more sophisticated checking logic.
Best regards,
Matthias
ConvergentFlow20120412.zip
- mkutscheid
- 309 Posts
- Index
- » Saddle Forum
- » User
- » Database poller to CSV file writer -...
Board Info
- Board Stats
- Total Topics:
- 119
- Total Polls:
- 0
- Total Posts:
- 800
- User Info
- Total Users:
- 960
- Newest User:
- rpjtate
- Members Online:
- 0
- Guests Online:
- 14
- Most Active Users:
- mkutscheid, dzungdev, Ortwin, aartik, cheikh, Mishra, sdanhardt, javega
- Online:
- There are no members online