<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Jeff Vannest&apos;s Weblog</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/" />
    <link rel="self" type="application/atom+xml" href="http://www.jandrconsult.com/blogs/jeff/atom.xml" />
   <id>tag:www.jandrconsult.com,2009:/blogs/jeff/3</id>
    <link rel="service.post" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3" title="Jeff Vannest's Weblog" />
    <updated>2009-10-05T14:37:22Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.2</generator>

<entry>
    <title>Upgrade Web Services in Oracle Application Server 10g</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2009/10/upgrade_web_ser_1.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=99" title="Upgrade Web Services in Oracle Application Server 10g" />
    <id>tag:www.jandrconsult.com,2009:/blogs/jeff//3.99</id>

    <published>2009-10-05T14:29:29Z</published>
    <updated>2009-10-05T14:37:22Z</updated>

    <summary> The OracleAS 10g software is, among other things, a robust application container for web services. It has integrated performance monitoring, web service clients, and several other add-ons that make it a pleasure to work with. However, all of this is built on top of a somewhat dated web service technology, Java API for XML-Based RPC (JAX-RPC). This article will describe the settings necessary to configure an OracleAS 10g web service to using the Java API for XML-Based Web Services (JAX-WS) technology....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="Technical Computing" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>
	The <a href="http://www.oracle.com/technology/products/ias/index.html" target="_blank">OracleAS 10g</a> software is, among other things, a robust application container for web services. It has integrated performance monitoring, web service clients, and several other add-ons that make it a pleasure to work with. However, all of this is built on top of a somewhat dated web service technology, <a href="http://java.sun.com/webservices/jaxrpc/overview.html" target="_blank">Java API for XML-Based RPC (JAX-RPC)</a>. This article will describe the settings necessary to configure an OracleAS 10g web service to using the <a href="http://jcp.org/en/jsr/detail?id=224" target="_blank">Java API for XML-Based Web Services (JAX-WS)</a> technology.</p>
]]>
        <![CDATA[<p>
	<b>Web Service Design Methods</b></p>
<p>
	Classically, web services are created using one of two methods, typically referred to as bottom-up or top-down. Using the bottom-up approach, the developer writes java classes (usually in the form of <a href="http://java.sun.com/products/ejb/" target="_blank">EJBs, or Enterprise JavaBeans</a>) that perform certain business functions then abstracts the design up into a <a href="http://www.w3.org/TR/wsdl" target="_blank">Web Services Description Language (WSDL)</a> document, which is a high-level XML document that is used to describe the web service. It is this document that might be used in a <a href="http://xml.coverpages.org/uddi.html" target="_blank">Universal Description, Discovery, and Integration (UDDI)</a> registry, which is a directory used to advertise the availability of web services.</p>
<p>
	On the other hand, the top-down approach begins with a WSDL document that is created by a business analyst or architect. From the WSDL and its associated XML schemas the developer creates java classes that implement the schema objects (usually in the form of <a href="http://xmlbeans.apache.org/" target="_blank">Apache XMLBeans</a> or <a href="http://java.sun.com/developer/technicalArticles/WebServices/jaxb/" target="_blank">Java Architecture for XML Binding (JAXB)</a> classes) and then writes web service methods on top of those classes that implement the business operation. While there is hot debate over which design method is best, suffice to say that there are very good reasons to use one method over another. For example, if the system running the web service does not already have its business objects and logic represented by EJBs, then the top-down approach is simpler and quicker to implement.</p>
<p>
	<b>Modifying OracleAS Libraries</b></p>
<p>
	In OracleAS 10g, a web service is installed as an <a href="http://www.oracle.com/technology/tech/java/oc4j/index.html" target="_blank">Oracle Container for J2EE (OC4J)</a>. Because each OC4J is a discretely running program within the application server, it is possible to use JAX-WS on a single OC4J without affecting the integrity of other web services running on the system.</p>
<p>
	First, the <a href="https://jax-ws.dev.java.net/2.1.7/" target="_blank">JAX-WS</a> java library files must be installed as shared libraries. In addition, if the <a href="http://jcp.org/en/jsr/detail?id=222" target="_blank">JAXB</a> java classes will be used to convert XML schemas described in the WSDL to java classes then an XML transformation library will be necessary as well; for example, <a href="http://saxon.sourceforge.net/" target="_blank">Saxon</a>. Implementing these as shared libraries means that the same files may be used by multiple web services in multiple OC4J instances without reloading the libraries into server memory more than once.</p>
<p>
	Second, the new OC4J must have several Oracle libraries de-registered so they do not conflict with the JAX-WS software. The easiest way to do this is to deploy the web service with a <a href="http://download.oracle.com/docs/cd/B25221_04/web.1013/b14431/deployplan.htm" target="_blank">deployment plan</a>. Whatever method is used, the following default Oracle libraries must be de-registered: oracle.jwsdl, oracle.ws.client, oracle.ws.jaxrpc, and oracle.xml.</p>
<p>
	<b>Summary</b></p>
<p>
	Although the removal of default Oracle libraries will make unavailable a few of the Oracle web service enhancements, the transition from JAX-RPC to JAX-WS web service technologies may be advantageous in certain situations. In the future, expect to see Oracle combine the standard java application server features of its <a href="http://www.oracle.com/appserver/weblogic/weblogic-suite.html" target="_blank">WebLogic Suite</a>, which already supports JAX-WS, with the enhanced administration features of the Oracle Application Server software.</p>
]]>
    </content>
</entry>
<entry>
    <title>Implementing B2MML In LIMS</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2009/09/implementing_b2.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=97" title="Implementing B2MML In LIMS" />
    <id>tag:www.jandrconsult.com,2009:/blogs/jeff//3.97</id>

    <published>2009-09-29T16:27:12Z</published>
    <updated>2009-09-30T16:29:36Z</updated>

    <summary> In the process of implementing an ERP to LIMS interface, one of the challenges to overcome was how to clearly communication between Oracle E-Business Suite (EBS) and SQL*LIMS v5. In the past, I had been exposed to several methods of interface communication, text files containing single bits of data, records inserted directly into a database, and concatenated strings transmitted over a network. Each of these methods had at least one serious flaw: if the data structure changed the interface stopped working. This article will review how Business To Manufacturing Markup Language (B2MML) was used to robustly transfer data and instructions between an ERP and LIMS system....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>
	In the process of implementing an ERP to LIMS interface, one of the challenges to overcome was how to clearly communication between <a href="http://www.oracle.com/us/products/applications/ebusiness/index.htm" target="_blank">Oracle E-Business Suite (EBS)</a> and <a href="http://www.sqllims.com/" target="_blank">SQL*LIMS v5</a>. In the past, I had been exposed to several methods of interface communication, text files containing single bits of data, records inserted directly into a database, and concatenated strings transmitted over a network. Each of these methods had at least one serious flaw: if the data structure changed the interface stopped working. This article will review how <a href="https://www.wbf.org/catalog/b2mml.php" target="_blank">Business To Manufacturing Markup Language (B2MML)</a> was used to robustly transfer data and instructions between an ERP and LIMS system.</p>
]]>
        <![CDATA[<p>
	<strong>History</strong></p>
<p>
	In late 2008 I had the opportunity to meet <a href="http://www.isa.org/Content/ContentGroups/Training3/Instructors/Dennis_Brandl.htm" target="_blank">Dennis Brandl</a>, member of the <a href="http://www.isa.org/MSTemplate.cfm?MicrositeID=275&amp;CommitteeID=4737" target="_blank">ISA-SP88</a> committee and <a href="http://www.wbf.org/" target="_blank">World Batch Forum (WBF)</a> Working Group. The context of the meeting was to help a global pharmaceutical manufacturing company use B2MML to communicate with auxiliary systems, including the company&#39;s LIMS. While the application of how B2MML might be used to express and communicate ERP data and decisions was clear, the task of teaching the LIMS system how to consume this data and return communication using B2MML was less clear. The company had already settled on using web services whenever possible, so my job was to work out the specific technologies that might be used to accomplish the task.</p>
<p>
	<strong>Challenge</strong></p>
<p>
	After reviewing the B2MML schemas, it became clear that the level of possible detail would be overwhelming. Further, while the schemas presented data using rational and coherent relationships, the overall data model looked nothing like LIMS data. For example, in a LIMS system, lots and samples are frequently created using information pulled from different parts of the system: a sample may require an attribute stored on the material, a lot may require an attribute stored on the lot plan, etc. When modeled into B2MML, the data required to log a LIMS lot might be spread out over several schemas, which made the creation and update of lots complex. To make the matter even more difficult, the LIMS needed to communicate back to the ERP using B2MML, which meant that the mapping of ERP data to LIMS data had to be bi-directionally accurate.</p>
<p>
	<strong>Solution</strong></p>
<p>
	To solve this dilemma, I chose to write an XML schema that described the SQL*LIMS lot and included the relationships to essential LIMS information such as lot dispositions, formulations, specifications, etc. With the LIMS data model fully described in an XML schema, I chose to use <a href="http://www.w3.org/TR/xslt" target="_blank">Extensible Stylesheet Language Transformations (XSLT)</a> to convert B2MML XML data into SQL*LIMS XML data. Therefore, when a web service received B2MML data from the ERP, an XSLT Stylesheet was used to transform the data into the LIMS&#39; schema and it was written to a table in the <a href="http://www.oracle.com/technology/tech/xml/xmldb/index.html" target="_blank">Oracle XML Database</a>, which was added to the database running the LIMS system.</p>
<p>
	This solution allowed all custom LIMS code to be read and written to a single data specification. In other words, instead of programming the LIMS to look for &quot;ERP Datum A&quot; and place it into &quot;LIMS Datum C&quot;, all code was simply written to read and write data to known locations. If the ERP system chose to move &quot;ERP Datum A&quot; to &quot;ERP Datum D&quot;, no LIMS API code needed to be modified. Instead, the XSLT Stylesheet was simply updated and placed on the LIMS web services host. Since changes to an XSLT would not be considered a &quot;code change&quot;, only brief acceptance testing would be conducted to verify that the flow of data was not interrupted between systems. Additionally, the ERP system could start sending new data at any time and the LIMS project could work on its own timeline without being concerned that the change in data would adversely affect the overall system.</p>
<p>
	<strong>Conclusion</strong></p>
<p>
	I am not aware of any LIMS system that has integrated B2MML communication. However, with a little help from web services and an XML schema mapping program, I believe any LIMS system could take advantage of this rich resource.</p>
]]>
    </content>
</entry>
<entry>
    <title>Interfacing SQL*LIMS v5 to a Global ERP</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2009/09/interfacing_sql.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=96" title="Interfacing SQL*LIMS v5 to a Global ERP" />
    <id>tag:www.jandrconsult.com,2009:/blogs/jeff//3.96</id>

    <published>2009-09-24T23:59:52Z</published>
    <updated>2009-09-25T21:06:25Z</updated>

    <summary>Most of this year has been spent designing and writing an interface between SQL*LIMS v5.1 and the new Enterprise Resource Planning (ERP) system being implemented by a global pharmaceutical manufacturing company. The goal was threefold: notify LIMS system administrators of changes made to materials, vendors, and manufactures; automatically create and update lots in the LIMS system; and send lot statuses and results from LIMS back to the ERP when testing was complete. This article will review the decision-making process used to plan and develop the interface....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>Most of this year has been spent designing and writing an interface between SQL*LIMS v5.1 and the new <a href="http://en.wikipedia.org/wiki/Enterprise_resource_planning" target="_blank">Enterprise Resource Planning (ERP)</a> system being implemented by a global pharmaceutical manufacturing company. The goal was threefold: notify LIMS system administrators of changes made to materials, vendors, and manufactures; automatically create and update lots in the LIMS system; and send lot statuses and results from LIMS back to the ERP when testing was complete. This article will review the decision-making process used to plan and develop the interface.<br />
</p>]]>
        <![CDATA[<p><strong>History</strong><br />
My work with this particular company started in 2002 when they were planning to replace their aging global LIMS system with SQL*LIMS v4.1. Although no development work had yet started, the decision to use a particular custom solution for interfacing had already been made. The interface was intended to move SQL*LIMS template data from a global configuration center into subscribing LIMS site instances, and to move <a href="http://en.wikipedia.org/wiki/Manufacturing_resource_planning" target="_blank">Manufacturing Resource Planning (MRP)</a> data between an existing MRP system and the new LIMS.</p>

<p>Although the MRP portion of the interface was deployed to a few sites in the United States and Europe for both SQL*LIMS v4.1 and v5, it soon became clear that the highly customized nature of the interface was slow and too difficult to support. The entire system was single-threaded, which meant that all transactions – both inbound and outbound – had to be processed one at a time. And, data was being transferred using an obtuse and hard-coded format; it was impossible to introduce new data into the system without causing a significant amount of technical rework and software re-release.</p>

<p><strong>Fresh Start</strong><br />
Soon after having completed the initial deployment of the first global LIMS instance in 2005, team members began hearing rumors that the company now wished to replace their aging MRP system. Although there were only two software packages that were finally considered for the new system, the company choose <a href="http://www.oracle.com/us/products/applications/ebusiness/index.htm" target="_blank">Oracle E-Business Suite (EBS)</a>. EBS is an incredibly robust system that would replace not only their original MRP system, but would implement new ERP software for financials, procurement, and several other aspects of running a global manufacturing company.</p>

<p>Therefore, the challenge given to me was how to interface SQL*LIMS v5 to an Oracle EBS? What data formats should be considered? What software should be used?</p>

<p><strong>Considerations</strong><br />
Even during the interface planning stages, I was given several options for implementing the interface. First, the new ERP could connect directly to our existing interface software, which meant that data would come in and out of the LIMS exactly as it had been planned back in 2002. Second, we could use a new data format and have the data placed either on the LIMS file system via FTP or into the LIMS database in a temporary table. Or third, we could choose to re-implement the interface using web services.</p>

<p>My very strong recommendation to this company was to use web services. Using this option meant that the LIMS system could take advantage of XML-based data exchange. This was very important to me because it meant that data being transferred between systems would be self-describing. No longer would changes in data definition break the interface or cause the re-release of interfacing components. Also, it meant that the interface could take advantage of the multi-threaded nature of a web server; transactions not requiring first-in, first-out processing could be executed in parallel, which would significantly increase the speed of the entire system.</p>

<p><strong>New Direction</strong><br />
SQL*LIMS v5 does not support web services, so whatever architecture was chosen had to extend the SQL*LIMS architecture in a manner that was consistent with the original application and would cause the least number of customizations to the vendor system. While many possible solutions were investigated, the following major components were chosen:</p>

<ul><li>Web services would be written to send and receive data. Each data transaction would have its own web service endpoint and would be packaged separately so that future enhancements would be easy to implement. This allowed the solution to leverage the SQL*LIMS application tier by running the web services from the Oracle Application Server, or from any production quality application server such as Oracle Weblogic, Sun Glassfish, etc.</li>

<p><li>Data would be transferred between the LIMS and ERP system using the <a href="https://www.wbf.org/catalog/b2mml.php" target="_blank">Business To Manufacturing Markup Language (B2MML)</a>. These XML schemas are explicitly designed to implement the <a href="http://www.isa.org/MSTemplate.cfm?MicrositeID=285&CommitteeID=4747" target="_blank">ANSI/ISA 95</a> family of standards, which help define the data that must move between ERP and manufacturing systems. By using open-standard XML schemas, the company was able to leverage the knowledge and experience of other manufacturing organizations and professionals all over the world.</li></p>

<p><li>An interface monitor would be added to run as a Windows service on the SQL*LIMS Business Logic Server (BLS), which is where the core of the SQL*LIMS monitors execute. The new monitor would process transaction data waiting in the queue table in the LIMS database, create lots, update lots, and send system notifications as required. Although adding a monitor introduced new custom code, it also allowed the solution to use existing architectural knowledge and training as a foundation for implementation.</li></p>

<p><li>A single Oracle form was added to the SQL*LIMS Utilities menu that allowed users to review inbound and outbound transactions and review transactions that had triggered errors. The form allowed the user to identify which transactions were legitimate errors, and which could be re-processed successfully.</li></ul></p>

<p><strong>Summary</strong><br />
I am often asked to make LIMS customizations. The first question I ask is, "Why?" Customizations can mean that a vendor product becomes unsupportable in the present and may remove it from the vendor upgrade path in the future. However, with the correct experience and knowledge, changes to a vendor product can be made to augment, rather than modify, existing functionality. These are the best customizations; these are the customizations that show pay-off for the time I spent and for the customer who must now support the system for the next several years. The keys are to use industry-standard technologies and methodologies and to leverage existing architecture, experience, and training.<br />
</p>]]>
    </content>
</entry>
<entry>
    <title>Completing a PDF Form using SQL*LIMS v5</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2008/12/completing_a_pd_1.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=94" title="Completing a PDF Form using SQL*LIMS v5" />
    <id>tag:www.jandrconsult.com,2008:/blogs/jeff//3.94</id>

    <published>2008-12-08T20:44:48Z</published>
    <updated>2008-12-09T15:29:32Z</updated>

    <summary>I am intrigued with the possibilities offered by the Applied Biosystems SQL*LIMS v5 architecture, which relies on the Oracle Application Server software for the on-screen forms and printed reports. Like the article, “XML Reporting in SQL*LIMS”, this article will use the Oracle AS software to implement a report using a PDF forms in SQL*LIMS v5....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>I am intrigued with the possibilities offered by the <a href="http://www.sqllims.com/" target="_blank">Applied Biosystems SQL*LIMS</a> v5 architecture, which relies on the Oracle Application Server software for the on-screen forms and printed reports. Like the article, “<a href="http://www.jandrconsult.com/blogs/jeff/archives/2007/05/xml_reporting_i.shtml" target="_blank">XML Reporting in SQL*LIMS</a>”, this article will use the Oracle AS software to implement a report using a PDF forms in SQL*LIMS v5.</p>]]>
        <![CDATA[<p>Similar to a Certificate of Analysis report used for manufactured product, the <a href="http://www.aphis.usda.gov/animal_health/vet_biologics" target="_blank">Veterinary Biologics Production and Test Report</a> is used to submit biologics data to the <a href="http://www.aphis.usda.gov/about_aphis/" target="_blank">United States Department of Agriculture Animal and Plant Health Inspection Service (APHIS)</a> after study completion but before product release. Unlike a pharmaceutical Certificate of Analysis report that can be generated directly out of the LIMS system, a blank copy of the APHIS 2008 report must be <a href="http://www.aphis.usda.gov/animal_health/downloads/aphis_forms/aphis2008.pdf" target="_blank">downloaded</a> from the USDA website and comes in the form of a Adobe PDF form template. Into this PDF file laboratory personnel must manually enter results into each of the boxes on the form using Adobe Acrobat. While this provides data to APHIS in a consistent format, manual completion of each PDF file is very time consuming.</p>

<p>In this article, I will describe a solution that can be used to automatically generate completed APHIS 2008 PDF forms directly from the SQL*LIMS v5 software.</p>

<p><strong>Standard SQL*LIMS Reporting</strong><br />
My previous article, “<a href="http://www.jandrconsult.com/blogs/jeff/archives/2007/05/xml_reporting_i.shtml" target="_blank">XML Reporting in SQL*LIMS</a>”, explains how reports work in the core SQL*LIMS product. In brief, a report is requested from the SQL*LIMS client, sent to the Oracle Reports server in the Oracle AS software, and the Oracle Report output is sent to the appropriate destination, the screen, a printer, a file, etc.</p>

<p><strong>Design Decision</strong>s<br />
During design, several issues needed to be address by this solution:<br />
1.	How to extract report data from the database<br />
2.	How to get the data into the federally-provided APHIS 2008 PDF form.<br />
3.	What to do with the completed form.</p>

<p><strong>Selecting Data</strong><br />
Like the previous XML reporting solution, all data was selected using a PL/SQL package. As before, this offered a greater range of algorithmic possibilities than provided in Oracle Reports, and placed all logic into a single location that was more easily maintained than an Oracle Report.</p>

<p>Using the data provided by the PL/SQL data extract package, this solution required that the Oracle Report output data in the <a href="http://partners.adobe.com/public/developer/en/xml/xfdf_2.0.pdf" target="_blank">Adobe XFDF</a> format. Similar to XML, this output format was easily reproducible in Oracle Reports, and allowed for the solution to remain consistent with the standard report execution method provided in the core SQL*LIMS software, the Run Events form, or automatic execution via status action.</p>

<p><strong>Placing XFDF data on the PDF</strong><br />
Because data formatted to the Adobe XFDF specification can be manually imported into an Adobe PDF form, the next issue to be addressed was how to cause this data importation to be automatically triggered. Fortunately, the <a href="http://www.lowagie.com/iText/" target="_blank">iText java library</a> provided the perfect solution for programmatically inserting XFDF data into an existing PDF form.</p>

<p>The iText library was used to create and implement a new <a href="http://www.oracle.com/webapps/online-help/reports/10.1.2/state/content/navId.3/navSetId._/vtTopicFile.htmlhelp_rwbuild_hs%7Crwwhthow%7Cwhatare%7Coutput%7Ca_plug_dest~htm">Pluggable Destination</a> in the Oracle AS server. This allowed the server to receive the XFDF data created by the Oracle Reports client, import the data into the APHIS PDF file using the iText java library, and save the completed PDF file to a user-selected folder on the server. Each file name is made unique by lot and specification name, as well as site location, and a report creation timestamp.</p>

<p><strong>Pluggable Destinations in SQL*LIMS</strong><br />
As before, a simple tweak to the EVENT_DISTRIBUTION_CLASS system parameter in SQL*LIMS allowed for events to be configured to the “PdfForm” destination. This modification to the software only allows the event to be executed in server mode, but this is actually a limitation intrinsic to the Oracle Forms software, which does not yet support Oracle Reports Pluggable Destinations in its internal APIs.</p>

<p><strong>Summary</strong><br />
As with any good technical solution, all of the technology in this solution is transparent to the SQL*LIMS user: The Veterinary Biologics event is executed using the Run Events form and a PDF file containing the requested LIMS data appears in a shared folder within seconds. And, while the solution was implemented specifically for the APHIS 2008 Veterinary Biologics report, the Pluggable Destination that was created to augment the Oracle AS server was created to be generic enough to work with future reports that require PDF form templates.</p>]]>
    </content>
</entry>
<entry>
    <title>I Like Your Mousetrap, Really!</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2007/09/i_like_your_mou.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=90" title="I Like Your Mousetrap, Really!" />
    <id>tag:www.jandrconsult.com,2007:/blogs/jeff//3.90</id>

    <published>2007-09-26T01:58:16Z</published>
    <updated>2007-09-28T03:11:34Z</updated>

    <summary>I’ve reflected on more than one occasion that independent consulting is a strange business. We’re neither vendor nor customer, although obviously, it’s in our best interest to be very friendly with both. It is, therefore, really problematic when an independent consultant gives opinions like “I wish customers acted like this,” or, “I wish vendors built things this way,” since the risk is that no matter what is said, it might be taken as criticism to someone, somewhere. But to state the obvious, this misunderstanding is not in the best interest of the independent consultant! So, let me say to whoever wishes to read it, “I really, really, really like your mousetrap!”...</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Consulting" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>I’ve reflected on more than one occasion that independent consulting is a strange business. We’re neither vendor nor customer, although obviously, it’s in our best interest to be very friendly with both. It is, therefore, really problematic when an independent consultant gives opinions like “I wish customers acted like this,” or, “I wish vendors built things this way,” since the risk is that no matter what is said, it might be taken as criticism to someone, somewhere. But to state the obvious, <em>this misunderstanding is not in the best interest of the independent consultant! </em>So, let me say to whoever wishes to read it, <u>“I really, really, really like your mousetrap!”</u></p>]]>
        <![CDATA[<p>The quote is attributed to Ralph Waldo Emerson as, “If a man can write a better book, preach a better sermon, or make a better mousetrap, than his neighbor, though he build his house in the woods, the world will make a beaten path to his door.” In contemporary society, the idea of building a better mousetrap is the idea that if you can improve on something essential, then you’ll be famous, rich, respected, whatever; you fill in the blank. Whether this is true or not is irrelevant to me, I only plan to filch the idea to make a point.</p>

<p>Just because a person wishes to build a better mousetrap does not mean that they dislike mousetraps! I like mousetraps, personally. We had a really large Norwegian rat that decided to reside with us when we lived outside of Detroit, Michigan. (We’re clean people, really!) But for whatever reason, this rat just decided that our house was cozy, pleasant, and friendly - whatever it is that rats go for when choosing a domicile - and he took up residence. In fact, one night he chewed a large hole in the wall not more than four feet from the desk chair where I sat every day doing LIMS consulting. So, as you can imagine, what I needed was a really good, rather large, mousetrap.</p>

<p>Buying a mousetrap is a pretty simple affair. I drove to Home Depot and in less than five minutes picked out the best looking trap I could find. I can tell you what never crossed my mind: I never once considered building my own mousetrap, not once. Why? Because my goals were very straight forward, I wanted one dead rat. No mess, no frills, no desire to wine and dine my rat before death, just one dead rat.</p>

<p>Somewhere out there are people who dream of better mousetraps. You know, the do-it-yourself engineer type of person who really enjoys thinking up new, cleaner, more humane, better mousetraps. I have nothing against these people, but their desires were not mine: they wish to <em>improve</em> the design; I wished to <em>use</em> the design. More power to them! Yes, my rat was dead within a week, but maybe the next generation of mousetraps will be better. Maybe I’ll just push a button and every rodent within a hundred yards will simply disappear into vapor…I don’t know…whatever that new-and-improved mousetraps will do.</p>

<p>Let me make my point: Dreaming of a better LIMS is my job…it’s what I do, and in some twisted way, I find it rewarding. Don’t hold it against me! I love the products that are on the market now, I look forward to new versions, improved interfaces, faster performance, standards based technology, etc. Please don’t think that because I pine for a better product, process, or whatever, that I dislike what’s out there. As I said above, it’s really not in my best interest to upset the apple cart, challenge the status quo, complain, disturb the balance, make a stink, stir things up…</p>

<p>…but a man’s gotta dream!</p>]]>
    </content>
</entry>
<entry>
    <title>XML Reporting in SQL*LIMS</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2007/05/xml_reporting_i.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=88" title="XML Reporting in SQL*LIMS" />
    <id>tag:www.jandrconsult.com,2007:/blogs/jeff//3.88</id>

    <published>2007-05-05T15:14:06Z</published>
    <updated>2007-05-07T19:41:21Z</updated>

    <summary>For several years my boss, Brian, has been telling me that the perfect solution for a LIMS Certificate of Analysis report would use a solid data extraction algorithm and a flexible XML output. The idea has always sounded interesting to me, except for the fact that the SQL*LIMS product doesn’t include the technology to do such a thing…until now. Today’s article describes how to customize SQL*LIMS and Oracle Reports to send data to XML, and how to convert that XML output to PDF....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>For several years my boss, <a href="http://www.jandrconsult.com/blogs/brian/index.asp">Brian</a>, has been telling me that the perfect solution for a LIMS Certificate of Analysis report would use a solid data extraction algorithm and a flexible XML output. The idea has always sounded interesting to me, except for the fact that the SQL*LIMS product doesn’t include the technology to do such a thing…until now. Today’s article describes how to customize SQL*LIMS and Oracle Reports to send data to XML, and how to convert that XML output to PDF.</p>]]>
        <![CDATA[<h3>Standard SQL*LIMS Reporting</h3>

<p>Normally, SQL*LIMS implements all reports using Oracle Reports Developer for both data selection and report layout. This solution is consistent with the core technology, but has several disadvantages. Foremost, Oracle Reports Developer is a confusing and unstable application. Any developer that has spent significant time creating Oracle reports can tell you the application crashes several times a day. Sometimes it crashes when copying and pasting layout objects, sometimes it crashes for no reason at all. Whatever the case, it’s frustrating to loose work, and seasoned developers learn to save their work obsessively. Also, Oracle Reports allows the developer to place programmatic triggers in many places throughout the application. Starting with the report properties form before and after triggers, programmatic logic can be executed in the data model, before and after triggers on the report body, and on every object in the report layout. The result is a confusing amalgam of logic that is spread out across dozens and dozens of program units, and executes in a very complex order, sometimes repeatedly. For all of its power, Oracle Reports Developer turns a simple reporting task into an advanced task, and an advanced reporting task into rocket science. For a complex report like a Certificate of Analysis, this solution becomes too cumbersome to maintain, not to mention the CPU cost of causing most of that processing to occur not in the Oracle Database server, but in the user’s client.</p>

<p>The following solution architecture was not my first choice. Oracle has a product called <a href="http://www.oracle.com/technology/products/applications/publishing/index.html" target="_blank">Oracle XML Publisher</a> that I believe would produce the same result as the customization described in this article. However, when we received requirements for a flexible output reporting solution from a customer recently, it was clear that requiring the purchase and implementation of Oracle XML Publisher would not be an option, since the decisions regarding architecture had already been made based on the software required by SQL*LIMS version 5.0.1. This architecture consists of <a href="http://www.oracle.com/technology/products/database/oracle10g/pdf/DS_General_Oracle_Database10gR2_EE_0605.pdf target="_blank"">Oracle 10g Database</a> and <a href="http://www.oracle.com/technology/tech/java/oc4j/10131/OracleAS-NF-10131.pdf" target="_blank">Oracle 10g Application Server</a>, which includes the Oracle Forms server to implement the SQL*LIMS software forms, and Oracle Reports server to implement SQL*LIMS reports.</p>

<h3>Design Decisions</h3>

<p>During design several questions needed to be answered:</p>

<p>1) How to extract data according to complex business rules in a manner that was quick to execute, yet simple to understand during software maintenance?<br />
2) How to get the selected data into an XML format?<br />
3) How to change XML data into a user-friendly report layout?<br />
4) How to change a user-friendly report layout into a format that could not be modified by the end user?</p>

<h3>Selecting Data</h3>

<p>We need to remove data selection out of Oracle Reports. The logical choice given the architecture is to place all data selection criteria into a database package. This is advantageous because it makes the implementation of business rules for selected data more transparent. Think of data selection in Oracle Reports like a system of tree roots; although it starts in one place in the data model, it quickly branches out into a complex system of tiny logical branches as the report executes group, frame, and item formatting triggers. Placing data selection in a database package forces the data selection algorithm into a single, straight line. Also, the package executes in the database, meaning that the user’s client is relieved of this computational task.</p>

<p>Another of the big advantages of using a database package is that the data selection algorithm can be modified without accidentally affecting report layout. In other words, the maintenance of business rules as implemented by report data selection is isolated from the rest of the solution, and may be modified by any developer with PL/SQL knowledge.</p>

<h3>Formatting Data to XML</h3>

<p>In order to format the data as XML, Oracle Reports Developer is used to create PL/SQL selection blocks in the data model. Each query returns a reference cursor from a function in the database package, and each field returned by the reference cursor is assigned a proper XML tag according to the desired reporting XML schema. The report does not require any layout, since when Oracle Reports executes to an XML format destination only XML data is output according to the order in which queries appear in the data model.</p>

<p>Placing XML formatting in an Oracle Report also allows this custom solution to stay within the SQL*LIMS v5 architecture, since Oracle Reports is already used for reports. So, the report is executed in SQL*LIMS either interactively using the Run Events form, or automatically using a server status action, and SQL*LIMS executes the Oracle Report, which uses the database package to select data, and outputs the data into XML.</p>

<h3>Making XML User-Friendly</h3>

<p>The next decision is how to make XML user-friendly. Fortunately, the <a href="http://www.w3.org/" target="_blank">World Wide Web Consortium</a>, or the W3C, has created <a href="http://www.w3.org/Style/XSL" target="_blank">XSL</a>, which stands for Extensible Stylesheet Language. In simple terms XSL is a family of standards that define the semantics for working with, presenting, and manipulating XML data. One member of this family is <a href="http://www.w3.org/TR/xsl/#fo-section" target="_blank">XSL-FO</a>, which allows XML data to be converted to a paginated, user-friendly format. Because this is a fairly complex transformation, it is necessary to use a helper application such as <a href="http://www.altova.com/products/stylevision/xslt_stylesheet_designer.html" target="_blank">Altova StyleVision</a>. This application takes XML data and allows it to be placed on the page in a user-friendly manner. The following is a screenshot from the Altova website.</p>

<p><em>Click image to see full sized</em><br />
<a href="http://www.jandrconsult.com/blogs/jeff/archives/images/StyleVision2006.gif" target="_blank"><img alt="StyleVision2006Sm.gif" src="http://www.jandrconsult.com/blogs/jeff/archives/StyleVision2006Sm.gif" width="500" height="395" /></a></p>

<p>For a developer that is comfortable with using an integrated development environment (IDE), this application turns stacks of XML data into simple fields that may be placed on the page similar to using Oracle Reports Developer, which for the purpose of comparison is shown in the following screenshot.</p>

<p><em>Click image to see full sized</em><br />
<a href="http://www.jandrconsult.com/blogs/jeff/archives/images/OracleReportsDeveloper.jpg" target="_blank"><img alt="OracleReportsDeveloperSm.jpg" src="http://www.jandrconsult.com/blogs/jeff/archives/OracleReportsDeveloperSm.jpg" width="500" height="375" /></a></p>

<h3>Converting XML to PDF</h3>

<p>The final component in this customization is to convert the XSL-FO transformation into PDF. This is the most technical part of the system, and requires both custom software and a modification to the Oracle Reports server.</p>

<p>While the ability to transform XML into a new markup format, XSL-FO, is a step in the right direction, a FO processor must be used to convert XSL-FO into PDF. For this, we must rely on <a href="http://xmlgraphics.apache.org/fop" target="_blank">Apache FOP</a>.</p>

<p>A FOP, which stands for formatting objects processor, takes XSL-FO markup and turns it into a paginated format such as RTF or PDF. While there are several FOPs on the market, most notably Oracle's own XML Publisher, we required a FOP that could be plugged directly into the SQL*LIMS v5 architecture and would not adversely affect previously made financial decisions. Apache FOP is both free, and as described below, could be plugged directly into the Application Server as an Oracle Reports Pluggable Destination.</p>

<p>Oracle 10g Application Server introduced <a href="http://www.oracle.com/webapps/online-help/reports/10.1.2/state/content/navId.3/navSetId._/vtTopicFile.htmlhelp_rwbuild_hs%7Crwwhthow%7Cwhatare%7Coutput%7Ca_plug_dest~htm" target="_blank">Pluggable Destinations</a>, which allow a developer to create and implement a custom destination in the Oracle Reports server. As a proof of concept, Oracle delivered the standard FTP destination using this new feature. Custom destinations are implemented as java servlets and are executed by Oracle Reports as an integrated part of the Application Server architecture.</p>

<p>It may occur to the astute technician that using an Oracle Reports Pluggable Destination to transform XML to PDF using XSL-FO is not consistent with the architecture. This is accurate: this is a change in <em>format</em> not a change in <em>destination</em>. However, the limitation is that Oracle Reports does not yet, nor will it likely ever, implement "Pluggable Formats" for Oracle Reports. Therefore, the only option is to output the report as XML and convert to PDF during the implementation of the destination.</p>

<p>Creating a Pluggable Destination that uses Apache FOP is fairly straight-forward for a knowledgeable java developer. Both are written in java, and the newest version of Apache FOP is thread safe, an absolute necessity when executing in a servlet environment. The final java jar is placed in the Oracle Reports jlib folder along with all font and metrics files, which enables the FOP to embed all fonts into the PDF document. During transformation, Apache FOP uses an XSL-FO file created by Altova StyleVision and the XML data that Oracle Reports stores in the cache to transform XML to PDF. After transformation, the servlet copies the PDF file out of the cache to a shared folder on the SQL*LIMS application tier. This folder is shared to permissible users as necessary.</p>

<h3>Pluggable Destinations in SQL*LIMS</h3>

<p>The standard SQL*LIMS version 5 software does not support Oracle Reports Pluggable Destinations. However, a simple tweak to the EVENT_DISTRIBUTION_CLASS system parameter allows events to be configured to the "Transform" destination. This modification to the SQL*LIMS software only allows the event to be executed in server mode, but this is actually a limitation intrinsic to the Oracle Forms software, which does not yet support Oracle Reports Pluggable Destinations in its internal APIs. Conveniently, the custom destination is passed through the SQL*LIMS Event Monitor without incident, and sent directly to the Oracle Reports server for processing.</p>

<h3>Summary</h3>

<p>All of this technology is transparent to the SQL*LIMS user. The Certificate of Analysis event is executed using standard methods (Run Events form or status action), and the PDF report appears in the user's file share using a filename that is specific to the laboratory, lot, protocol, and date and time. If a change in business requirements is necessary, only the database package is affected. If a change in report layout, page size, or selected columns is necessary, only the StyleVision transform file is affected. In the final implementation, users are allowed to select from one of several report formats, meaning that the same data can be presented in a layout that is sensitive to language, market, region, or specification.</p>

<p>Best of all, the new functionality is based on international standards, with a bare minimum of modifications made to the vendor-provided SQL*LIMS software.<br />
</p>]]>
    </content>
</entry>
<entry>
    <title>Oracle Technology Day 2005</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2006/03/oracle_technolo_1.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=80" title="Oracle Technology Day 2005" />
    <id>tag:www.jandrconsult.com,2006:/blogs/jeff//3.80</id>

    <published>2006-03-09T21:55:46Z</published>
    <updated>2006-03-12T02:05:38Z</updated>

    <summary>A day off work is always welcome – especially when it comes under the guise of &quot;professional training.&quot;...</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="Technical Computing" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>A day off work is always welcome – especially when it comes under the guise of "professional training."</p>]]>
        <![CDATA[<p>I arrived at the Walt Disney World Dolphin Resort for Oracle Technology Day 2005. As an aside, I’m so thrilled to live in Orlando, Florida. I grew up in the Flint, Michigan area where the only tourist attraction is the half of the city that closed in the early 1980’s when GM closed up almost overnight (see Michael Moore’s <a href="http://www.imdb.com/title/tt0098213/">Roger & Me</a>). So, I’m regularly surprised that I live so close to gorgeous and luxurious resort locations.</p>

<p>What’s up with a conference starting at 8:00AM with an one hour breakfast? Do these people not have homes with kitchens? Here’s the thing: I’m busy enough that I don’t actually read the schedule when I attend these things, so when I arrive at 7:50AM I expect things to start in 10 minutes. Instead, I got the chance to sit around and observe people, find out who’s who, and generally exercise my social muscle for a full 80 minutes.</p>

<p>People are fascinating and the technical crowd is no different. You have several types of people that will attend a technical conference, but I'd like to pick on only those with which I came into contact. The first person I sat down next to was a "Self-Trained," which is a person that learns everything on his or her own. I’m a self-trained, so this type is one I’m pretty familiar with: learned the technology during some historical task when a one-off solution was chosen by the employer and then became the resident "expert". My experience is that the older the Self-Trained, the more arcane the technology. The reason for this is simple: self-training takes lots of time, so keeping up with the "newest" thing becomes hard to do without outside motivation.</p>

<p>The next person I met was at the breakfast table. I noticed him immediately because he was actually wearing the Oracle baseball cap that every attendee received at the registration desk. He was also wearing – are you sitting down? – a Microsoft monogrammed oxford shirt. Who does this? The "Conference Junkie", that’s who! This type walks through local malls wearing a Cisco hat, carries an IBM duffle bag, and writes with an oversized Seibel ink pen.</p>

<p>The final type I will mention is the "Casual Technologist", which was represented at this conference by the two DBAs sitting at my table. Coming from a very large local government contractor, these guys mostly talked about how they intended to spend the day at one of the Disney World theme parks instead of learning about the newest Oracle technologies. To prove the point, they packed up their belongings and left the conference before the 9AM start time.</p>

<p>The title of this conference was "Compliance to the Core", which immediately piqued my interest. Being a LIMS consultant offers regular opportunities to deal with compliance issues. However, this type of compliance is different from CFR part 11 compliance. To get a handle on this type of compliance, think of the following hypothetical event: An executive from a major energy or financial company sends out false or inaccurate data in order to make the financial position of the company look more solid to shareholders and the financial community. From a culpability point of view, the company itself must be able to show that the timeliness and quality of the internal data available to that executive is not blamed for the release of inaccurate data. Enter "business intelligence."</p>

<p>Although the push is somewhat new to Oracle, the idea of business intelligence is very old: "Summarize for me all the data I have permission to see in a way I can understand and make certain it’s up to date!" Sound easy? Wrong! Typically, I see people reviewing only the data they can get, regardless of whether they should get it, or whether it is the right data, or whether they have the mathematical skill to summarize the data in ways that are accurate or meaningful. So, functional business intelligence is very good news, since it is an attempt by Oracle to place data storage, warehousing, mining, transformation, reporting, security, and dashboard-like summarization all under a unified application interface. This is excellent news for the LIMS industry, since it means that big, corporate businesses are increasingly interested in things that the average pharmaceutical company is interested in, which is, secured data delivered reliably.</p>

<p>I'm looking forward to seeing what affect this new push on business intelligence has on the LIMS industry long term. Is it possible, for example, that this more interactive front end could replace the somewhat inflexible reporting interfaces currently offered in several LIMS programs?</p>]]>
    </content>
</entry>
<entry>
    <title>How to create an FTP Interface in SQL*LIMS</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/11/creating_an_ftp.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=75" title="How to create an FTP Interface in SQL*LIMS" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.75</id>

    <published>2005-11-02T14:04:51Z</published>
    <updated>2005-11-03T00:06:54Z</updated>

    <summary>I&apos;ve demonstrated the creation of two types of custom interfaces in SQL*LIMS version 4.1: email and memo. The final interface type I&apos;d like to demonstrate is FTP. First, let me qualify that I don&apos;t believe the creation of a custom FTP interface using PL/SQL is the best solution. However, I can certainly see advantages and simplicity in transferring data directly from a programmatic procedure without needing to write it to the sending file system or relying on complex transfer software such as IBM WebSphere MQ. Therefore, let&apos;s assume there is some compelling reason that an FTP client integrated into the PL/SQL environment is preferable and simply move on to a proof of concept....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>I've demonstrated the creation of two types of custom interfaces in SQL*LIMS 
version 4.1: email and memo. The final interface type I'd like to demonstrate is 
FTP. First, let me qualify that I don't believe the creation of a custom FTP 
interface using PL/SQL is the best solution. However, I can certainly see 
advantages and simplicity in transferring data directly from a programmatic 
procedure without needing to write it to the sending file system or relying on 
complex transfer software such as IBM WebSphere MQ. Therefore, let's assume 
there is some compelling reason that an FTP client integrated into the PL/SQL 
environment is preferable and simply move on to a proof of concept.</p>]]>
        <![CDATA[<p>The most fundamental piece of an FTP server is the ability to send packets of 
data from one network location to another. Fortunately, the Oracle database has 
built-in networking functionality that is made accessible through the core 
utl_tcp package. Using this core functionality and a few pieces of information 
we can create an FTP interface that can be called directly from a custom PL/SQL 
package to send a file from one server to another.</p>

<p>
There are certain security aspects that I will skim over in this article: 1) 
using FTP with secured user access, 2) document storage and access, and 3) 
access to the interface itself. Each of these aspects is important to overall 
system security, but I will not take the time to demonstrate secure solutions in 
this article.</p>

<p>
To setup the system, we'll create two system defaults: FTP - HOST and FTP - 
PORT. These indicate the server and port (typically port 21) to which files will 
be sent. Because we need to collect system defaults programmatically, we will 
plan to use the sys_default function that was described in the
<a href="http://www.jandrconsult.com/cgi-bin/mt/mt-tb.cgi/66">Creating an Email 
Interface in SQL*LIMS</a> article.</p>

<p>
Here's the code that we'll use for the PL/SQL FTP interface with line numbers 
for clarity:</p>
<pre>
1  CREATE OR REPLACE PROCEDURE send_ftp(name_in IN VARCHAR2,
2        file_in IN VARCHAR2) AS
3     v_cmd VARCHAR2(4);
4     v_datconn utl_tcp.connection;
5     v_conn utl_tcp.connection;
6     v_port_add PLS_INTEGER;
7     v_port_dec PLS_INTEGER;
8     v_reply VARCHAR2(512);
9     v_stat PLS_INTEGER;
10 BEGIN
11    v_conn := utl_tcp.open_connection(sys_default('FTP - HOST'),
12       sys_default('FTP - PORT'));
13    
14    WHILE NVL(v_cmd,'x') != '221 ' LOOP
15       IF v_cmd = '220-' THEN
16          v_stat := utl_tcp.write_line(v_conn, 'USER anonymous');
17       ELSIF v_cmd = '331 ' THEN
18          v_stat := utl_tcp.write_line(v_conn, 'PASS me@here.com);
19       ELSIF v_cmd = '230 ' THEN
20          v_stat := utl_tcp.write_line(v_conn, 'PASV');
21       ELSIF v_cmd = '227 ' THEN
22          v_reply := substr(v_reply, instr(v_reply, '(',1,1)+1,
23             instr(v_reply, ')',1,1) - instr(v_reply,'(',1,1)-1);
24          v_port_dec := substr(v_reply, instr(v_reply,',',1,4)+1,
25             (instr(v_reply,',',1,5) - (instr(v_reply,',',1,4)+1)));
26          v_port_add := substr(v_reply, instr(v_reply,',',1,5)+1,
27             length(v_reply) - instr(v_reply,',',1,5));
28          v_datconn := utl_tcp.open_connection(
29             sys_default('FTP - HOST'),
30             (v_port_dec * 256)+v_port_add);
31          v_stat := utl_tcp.write_line(v_conn, 'STOR ' || name_in);
32       ELSIF v_cmd = '125 ' THEN
33          v_stat := utl_tcp.write_text(v_datconn, file_in);
34          utl_tcp.close_connection(v_datconn);
35       ELSIF v_cmd = '226 ' THEN
36          v_stat := utl_tcp.write_line(v_conn, 'QUIT');
37       END IF;
38       v_stat := utl_tcp.read_line(v_conn, v_reply);
39       v_cmd := SUBSTR(v_reply, 1, 4);
40    END LOOP;
41    
42    utl_tcp.close_connection(v_conn);
43 EXCEPTION WHEN OTHERS THEN
44       dbms_output.put_line('ERROR: ' || SQLERRM);
45       utl_tcp.close_all_connections();
46 END send_ftp;</pre>

<p>Lines 11-12 use the System Default function to return the FTP host and port 
number and the UTL TCP Package Open Connection function to open a connection to 
the server.</p>

<p>
Lines 14 and 40 open and close a loop to step through the server's responses. 
This is necessary because FTP servers return a varying number of text lines when 
responding to certain commands. Lines 15 through 37 contain an IF block that 
contains each of the commands to which we need to respond.</p>

<p>
Line 16 and 18 send the username and password to the server. These values would 
normally be stored in a secure location, and would not use an anonymous login.</p>

<p>
Line 20 tells the FTP server to enter
<a href="http://slacksite.com/other/ftp.html">passive mode</a>, which allows the 
client to contact the server with a new data port.</p>

<p>
Lines 22 through 27 calculate the port on which data will be sent. The standard 
FTP protocol operates on two ports, the command port, which is typically 21, and 
the data port, which can be any port above 1024. Because servers are frequently 
contacted from outside the current network, traffic on the command port usually 
passes through firewalls and routers easily. Once the connection is made, the 
FTP client specifies the passive mode and calculates a new, unprivileged, or 
private, port on which to send the file data.</p>

<p>
Line 28 through 30 opens the data port, and line 31 tells the server to store 
the incoming data as a specific file name.</p>

<p>
Lines 33 through 34 send the file data and close the data port.</p>

<p>
Line 36 tells the FTP server that we intend to quit, and line 42 carries it out.</p>

<p>
To test the interface, start an FTP server that accepts anonymous connections 
and modify the FTP - HOST and FTP – PORT SQL*LIMS system defaults to contain the 
server information. Open SQL*PLUS as the SQL*LIMS Owner and execute the 
following:</p>

<pre>exec send_ftp('test.txt', 'Very cool FTP transfer, I must say!');</pre>

<p>
Look in the root directory of the FTP server for a file named test.txt, it 
should contain the sentence, &quot;Very cool FTP transfer, I must say!&quot; If it does 
not, try logging into the FTP server from a command prompt using the information 
stored in the FTP - HOST and FTP – PORT SQL*LIMS system defaults. This will 
verify that the server does, in fact, accept anonymous connections.</p>

<p>
Overall, our FTP client is decently prepared for standard text file transfer, 
but lacks robustness. If we were looking to add features, we would allow the 
procedure to accept the file as an Oracle CLOB, support binary transfer modes, 
look to see if the filename already exists on the destination system, more 
adroitly handle common error conditions, etc. Finally, we’d want to build in 
some kind of queuing mechanism so that if the destination server were 
unavailable for some reason we wouldn’t loose our data. That would not make us 
happy!</p>]]>
    </content>
</entry>
<entry>
    <title>The &quot;S&quot; Reality</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/10/the_s_reality.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=77" title="The &quot;S&quot; Reality" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.77</id>

    <published>2005-10-21T00:48:42Z</published>
    <updated>2005-11-04T19:51:44Z</updated>

    <summary><![CDATA[Good consulting is based on good decision-making. Good decision-making is supported by knowledge, experience, and the quality ideal. Because I have a particular interest in the formation and expression of quality, I was fascinated by a certain book I am reading about the &quot;S&quot; reality....]]></summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="Personal Development" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>Good consulting is based on good 
decision-making. Good decision-making is supported by knowledge, experience, and 
the quality ideal. Because I have a particular interest in the formation and 
expression of quality, I was fascinated by a certain book I am reading about the 
&quot;S&quot; reality.</p>]]>
        <![CDATA[<p>You probably wonder what the &quot;S&quot; 
stands for; however, I wish this word to be anonymous for now. The reason for 
this is legitimate: I wish the reader to see objectively how a certain view of 
the world might affect our ideas of quality, concept formation, value, and even 
the nature of reality itself, without being biased by prejudgments. Tall order? Yes, I suppose it is. You can be the 
judge of how well I succeed.</p>


<p>The &quot;S&quot; reality describes our 
primary reality; it is the context from which our world is observed, and the 
basis from which we think our thoughts. Based on this description, you can 
determine that this reality is intangible since I described it not as &quot;our 
world&quot; and &quot;our thoughts&quot;, but as &quot;the context&quot; and &quot;the basis&quot;. For the sake of 
this explanation, I will describe the &quot;S&quot; reality as nonphysical, powerful, 
thoughtful, and valuing, and will give examples of each.</p>


<p><b>NONPHYSICAL:</b> The &quot;S&quot; reality 
cannot be detected by the five senses but is self-evident. It 
has neither size, shape, weight, color, flavor, order, nor texture. For example, 
a <i>thought of </i>or a <i>wish for </i>a new AMD Athlon 64 X2 4400+ are 
trivial examples of things that are undetectable by the senses, but are real in 
every sense of the word. They – the <i>thought</i> and <i>wish</i> - can be 
described clearly, communicated to and experienced by others, and yet cannot be 
physically sensed. In another example, my physical body can be said to house 
&quot;me&quot;, yet if I were dissected, you would not find &quot;me&quot;. Somehow, although a 
&quot;me-ness&quot; is <i>localized</i> in my physical body, it is not <i>located</i> 
there. Similarly, the &quot;S&quot; reality is <i>localized</i> to all things, but not <i>
located</i> there.</p>


<p><b>POWERFUL:</b> The &quot;S&quot; reality has 
unlimited power and energy. For example, if you look around, you probably see a 
room full of objects that came to be there because of the feelings, ideas, and 
wills of one or more persons. If you look to any road you will see a car that 
was created by the power and energy of the &quot;S&quot; reality…the unabashed persistence 
of a group of people determined to make a metal and plastic object capable of 
moving on land faster than another living thing. Do you doubt for one 
second that it took a tremendous amount of creative energy to create this thing? 
Cars don't grow on trees, so of course it did! The &quot;S&quot; reality contains enough 
energy for every one of us to build extraordinary things.</p>


<p><b>THOUGHTFUL: </b>The &quot;S&quot; reality is the 
primary context for rational thought. What is a human being but a large 
collection of focused cognition? Our brains simply direct experience, knowledge, 
and will upon the various subjects and matters that concern them. Furthermore, 
no physical thing has thought; even my own brain, if placed outside of the body 
that describes my &quot;me-ness&quot;, does not have thought. So, while a thought can be 
described by chemistry, it is not simply chemical; while &quot;I&quot; can be described by 
biology, I am not simply biological.</p>


<p><b>VALUING:</b> From the &quot;S&quot; reality and 
it's thoughtful context described above we receive the drive to determine value. 
Based partly on feeling, the ability to concentrate rational thought on personal 
choices is provided through this reality. Without it, we have neither the 
context for rational thought nor the creative energy to affect our value choices 
on the world around us.</p>


<p>Although I have only briefly 
described several aspects of the &quot;S&quot; reality, I find it completely compelling. 
What could each of us do if we had 1) the assurance that our primary reality was 
integral to our being, 2) the unlimited creative energy to affect the world 
around us, 3) a firm context for rational thought, and 4) the context from which 
to choose value in our actions? A lot, that's what!</p>


<p>Now comes the part where I tell 
you my anonymous word and the title of the book I'm reading; or I don't. No, I 
don't think I will. Instead, I leave that search to you. Here are some hints:</p>

<p>1) The word appears in the J&amp;R 
Mission statement</p>

<p>2) A reverse lookup on the word 
might be: Of, relating to, consisting of, or having the vital principle or 
animating force present within living beings; not tangible or material.</p>


<p>Good luck in the search.</p>]]>
    </content>
</entry>
<entry>
    <title>How to create a Memo Interface in SQL*LIMS</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/10/creating_a_memo.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=72" title="How to create a Memo Interface in SQL*LIMS" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.72</id>

    <published>2005-10-12T20:44:06Z</published>
    <updated>2005-10-31T03:24:50Z</updated>

    <summary>In my last article, I demonstrated how to create an email interface in SQL*LIMS version 4.1. Such an interface provides robust functionality but there is a catch: using email for CFR 11-related communication is difficult to validate, and in many companies, may function as the sole method of notification. To get around these concerns, SQL*LIMS offers the memo, which is an application-specific notification stored in the Oracle database. However, like sending emails, the SQL*LIMS application does not offer a programmatic interface to the memo system. This article will demonstrate how to create a simple interface that will send a memo to a LIMS user when a custom program encounters an error....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>In my last article, I demonstrated how to create an email interface in SQL*LIMS version 4.1. Such an interface provides robust functionality but there is a catch: using email for CFR 11-related communication is difficult to validate, and in many companies, may function as the sole method of notification. To get around these concerns, SQL*LIMS offers the memo, which is an application-specific notification stored in the Oracle database. However, like sending emails, the SQL*LIMS application does not offer a programmatic interface to the memo system. This article will demonstrate how to create a simple interface that will send a memo to a LIMS user when a custom program encounters an error.</p>]]>
        <![CDATA[<p>Compared to creating an email interface, the memo interface is very simple. Here is the send memo procedure with line numbers added for clarity:</p>

<pre>1  CREATE OR REPLACE PROCEDURE send_memo(notify_in IN VARCHAR2,
body_in IN VARCHAR2) AS
2     v_document_id NUMBER;
3     v_r_status NUMBER;
4  BEGIN
5     naip_utility.counter(v_document_id, 'SERIAL', v_r_status);
6  
7     INSERT INTO nai_documents
8        (document_id, document_version, file_class,
9       document_clob, status, userstamp, timestamp)
10    VALUES
11       (v_document_id, 1, 'INTERNAL',
12       body_in, 'NEW', USER, SYSDATE);
13 
14    INSERT INTO nai_memos (userstamp, receiver, timestamp,
15       document_id, status, origin)
16    VALUES (REPLACE(USER, 'OPS$'), notify_in, SYSDATE,
17       v_document_id, 'NEW', 'Send Memo Procedure');
18    commit;
19 EXCEPTION
20    WHEN OTHERS THEN
21       dbms_output.put_line('ERROR: ' || SQLERRM);   
22 END send_memo;
23 /
</pre>
<p>Line 7 returns a document ID from the serial counter and uses the core SQL*LIMS Utility package to do so. This ID associates a master memo record with a detail record.</p>
<p>Lines 7-12 insert the memo into the Documents table, use the standard file_class of INTERNAL, and a status of NEW. When the user selects the memo using the Read Memos form, the status automatically changes to READ. This feature sets the SQL*LIMS memo apart from internet email because the storage and receipt of the notification is guaranteed unlike internet email, whose storage and delivery is not guaranteed.</p>
<p>Lines 14-17 insert the user notification records into the Memos table. This will cause the SQL*LIMS status bar to display a message to the user that a notification is waiting to be read. The origin column is set to &ldquo;Send Memo Procedure&rdquo;, although any value may be used.</p>
<p> So, we've reviewed the code; let's give this a test run. Log into SQL*Plus using the LIMS Owner account for the SQL*LIMS instance. This account is the user that owns the LIMS instance, for example ops$penlims. At the SQL*Plus prompt enter:</p>

<pre>exec send_memo(REPLACE(USER, 'OPS$'),
'Your tests look terrific, you get a raise.');</pre>

<p>SQL*Plus responds &quot;PL/SQL procedure successfully completed&quot;, and the LIMS Owner will immediately receive a SQL*LIMS memo that can be reviewed using the Read Memo form.</p>
<p>Using the new procedure in the application is simple: when an event occurs in a status action or custom program that should result in a user notification, execute the send_memo procedure and supply the LIMS User and the text of the notification.</p>
<p>We now have SQL*LIMS email and memo interfaces. For a more robust solution, the two procedures may be combined into a single messaging interface that sends notifications to either email or the memo system based on either programmatic input or a system flag such as a System Default.In my next article, I will describe how to create a simple FTP interface that can be used in a SQL*LIMS status action to send a file to another server.</p>]]>
    </content>
</entry>
<entry>
    <title>How to create an Email Interface in SQL*LIMS</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/09/creating_an_ema.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=69" title="How to create an Email Interface in SQL*LIMS" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.69</id>

    <published>2005-09-18T02:40:42Z</published>
    <updated>2005-10-12T21:20:21Z</updated>

    <summary>In SQL*LIMS, a PL/SQL package can be installed as an event and attached as a status action in any template or instance object level. This offers the LIMS developer a robust environment in which to execute a wide variety of custom actions. For example, most versions of SQL*LIMS come with an example PL/SQL procedure for executing cross-task calculations. However, in order to make this example code robust enough for regular use, a developer would need to supplement it with things like...error handling! This article will demonstrate how to create a simple interface that will allow emails to be sent to a LIMS user when a PL/SQL package encounters an error....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>In SQL*LIMS, a PL/SQL package can be installed as an event and attached as a status action in any template or instance object level. This offers the LIMS developer a robust environment in which to execute a wide variety of custom actions. For example, most versions of SQL*LIMS come with an example PL/SQL procedure for executing cross-task calculations. However, in order to make this example code robust enough for regular use, a developer would need to supplement it with things like...error handling! This article will demonstrate how to create a simple interface that will allow emails to be sent to a LIMS user when a PL/SQL package encounters an error.</p>]]>
        <![CDATA[<p>The most important piece of an interface that sends emails is the SMTP server. Fortunately, the Oracle database has a built-in server that is made accessible through the core utl_smtp package. Using this package and a few system defaults, we can create an email interface that is called from a PL/SQL package to deliver emails to LIMS users.</p>
<p>To setup the system, we'll create two system defaults, EMAIL - SMTP SERVER and EMAIL - SMTP PORT. The server default indicates the name of the SMTP server used by your company to send email, and the port default indicates the TCP port number on which the server is listening. These values are typically something like &quot;mail.jandrconsult.com&quot; and &quot;25&quot;, so these will be the example values. We also need to store a user's email address, so use the Define User Classes form and the Address tab in SQL*LIMS to create a new class called EMAIL. Next, use the Define Users form and User Information block on the Names tab to store the LIMS Owner's email address. For example:</p>
<pre><strong>Seq    Address Class      Address Line</strong><br/>
1      EMAIL              Jeff.Vannest@jandrconsult.com </pre>
<p>Now to make the design as modular as possible, create a function and procedure for the collection of email addresses and system defaults. Here are some very simple examples:</p>
<pre><font size="small">CREATE OR REPLACE PROCEDURE create_email_list(notify_in IN VARCHAR2,
	send_to_name_out OUT VARCHAR2, send_to_noname_out OUT VARCHAR2)
AS
BEGIN
	SELECT '"' || last || ', ' || first ||
	'" ' || addr_line, addr_line
	INTO send_to_name_out, send_to_noname_out
	FROM nais_addresses a, nais_usernames u
	WHERE u.userid = a.userid
		AND a.userid = REPLACE(UPPER(notify_in), 'OPS$', NULL)
		AND a.class = 'EMAIL'
		AND rownum = 1;
END create_email_list;
/

CREATE OR REPLACE FUNCTION sys_default(name_in VARCHAR2)
	RETURN VARCHAR2
AS
	v_response nais_system_defaults.value%TYPE;
BEGIN
	SELECT VALUE
	INTO v_response
	FROM nais_system_defaults
	WHERE UPPER(name) = UPPER(name_in);
	RETURN v_response;
END sys_default;
/</font></pre>
<p>Of course, these examples need things like good error handling, code comments, and input parameter checking, but you get the idea. Here is the send email procedure with line numbers added for clarity:</p>
<pre>1  CREATE OR REPLACE PROCEDURE send_email(body_in IN VARCHAR2,
2        subject_in IN VARCHAR2, notify_in IN VARCHAR2)
3  AS
4     v_full_body VARCHAR2(10000);
5     v_owner_name VARCHAR2(1000);      
6     v_owner_noname VARCHAR2(1000);      
7     v_mail_conn utl_smtp.connection;   
8     v_reply utl_smtp.reply;      
9     v_send_to_name VARCHAR2(1000);      
10    v_send_to_noname VARCHAR2(1000);      
11    v_smtp_server nai_system_defaults.value%TYPE;
12 BEGIN
13    create_email_list(notify_in, v_send_to_name, v_send_to_noname);
14    create_email_list(USER, v_owner_name, v_owner_noname);
15
16    v_smtp_server := sys_default('EMAIL - SMTP SERVER');
17    v_mail_conn := utl_smtp.open_connection(v_smtp_server,
sys_default('EMAIL - SMTP PORT'));
18
19    v_reply := utl_smtp.helo(v_mail_conn, v_smtp_server);
20    v_reply := utl_smtp.mail(v_mail_conn, v_send_to_noname);
21    v_reply := utl_smtp.rcpt(v_mail_conn, v_owner_noname);
22
23    v_full_body := 'To: ' || v_send_to_name || CHR(10) ||
24       'From: "' || USER || '" ' || v_owner_noname || CHR(10) ||
25       'Subject: ' || subject_in || CHR(10) ||
26       'Content-Type: text/html' || CHR(10) || CHR(10) ||
27       '&lt;HTML>&lt;BODY>&lt;P>&lt;PRE>' || CHR(10) ||
28       body_in ||
29       '&lt;/PRE>&lt;/P>&lt;/BODY>&lt;/HTML>';
30
31    v_reply := utl_smtp.data(v_mail_conn, v_full_body);
32    v_reply := utl_smtp.quit(v_mail_conn);
33
34 END send_email;
35 /</pre>
<p>Lines 13 and 14 use the create_email_list created earlier to create the proper email address lines that the SMTP server expects. You'll notice that each call to the procedure returns the user's name and email address twice, once with the name included, and once without. These are intentional and will help the user see the name and email address of the sending and receiving users normally when receiving an email message. Line 14 uses the Oracle keyword &quot;USER&quot;, which indicates that we assume this procedure will be executed by the LIMS Owner.</p>
<p>Lines 16 and 17 retrieved the name of the SMTP server name stored as a system default, and opened a connection to the mail server using the port specified by the appropriate system default.</p>
<p>Lines 19, 20 and 21 are used to introduce ourselves to this particular SMTP server, who comes from a long line of aristocratic servers and appreciates the formality.</p>
<p>Lines 23 through 29 construct the email message. Notice that simple HTML tags are used in lines 27 and 29 to wrap the body of the email message, which is consistent with the content type shown in line 26. If all of this technical detail sounds foreign don't be concerned; simply know that using pre-formatted HTML in the message body allows the text to be formatted for easy reading.</p>
<p>Finally, line 31 sends the full message text and line 32 says, &quot;Good day, sir, I had a wonderful chat. My regards to your lovely wife.&quot;</p>
<p>So, we've reviewed the code; let's give this a test run. Log into SQL*Plus using the LIMS Owner account for the SQL*LIMS instance. This account is the user that owns the LIMS instance, for example ops$penlims. At the SQL*Plus prompt enter:</p>

<pre>exec send_email(USER, 'Hello LIMSWorld!',
'Your tests look terrific, you get a raise.');</pre>

<p>SQL*Plus responds &quot;PL/SQL procedure successfully completed&quot;, and in a few minutes, the LIMS Owner will receive an email message at the address defined in the Define Users form. If this is not the response, then review the values of the SMTP system defaults.</p>
<p>Using the new procedure is simple: when an event occurs in a status action or PL/SQL event that should notify a user, execute a call to the send_email procedure and supply the LIMS User to which the message should be sent, the subject of the email, and the text body of the email.</p>
<p>In my next article, I'll describe how to create a simple PL/SQL interface to the SQL*LIMS memo system.</p>]]>
    </content>
</entry>
<entry>
    <title><![CDATA[J &amp; R Productivity Tips]]></title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/07/jr_productivity.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=68" title="J &amp;amp; R Productivity Tips" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.68</id>

    <published>2005-07-16T16:11:56Z</published>
    <updated>2005-09-25T18:12:21Z</updated>

    <summary><![CDATA[In an effort to discover the most productive methods of work, I asked every consultant at J&amp;R Consulting, Inc. the same question, &quot;What productivity habits do you use regularly?&quot;...]]></summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="General Consulting" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>In an effort to discover the most productive methods of work, I asked every consultant at J&amp;R Consulting, Inc. the same question, &quot;What productivity habits do you use regularly?&quot;</p>]]>
        <![CDATA[<p>Four out of ten responses identified the use of a task list to make work time more productive. Whether written or mental, a task list allows a person to concentrate heavily on one task while not being concerned that other tasks are forgotten. In conjunction with the task list, two responses further qualified the task list as being arranged by priority and broken down into smaller, sub-tasks. This kind of structured planning allows work to be executed within acceptable timeframes and insures that delivered work is complete &ndash; or at least considered. At J&amp;R, we use a custom forms tool within <a target="_blank" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/06/jr_technical_ti.shtml">Groove</a> to identify, prioritize, and break down tasks. All tasks in the tool are visible to all members, and changes to tasks are automatically distributed to all team members connected to the Internet. Tasks can be assigned to other team members, and certain types of metrics can be gathered based on task completion, hours assigned, hours estimated, percent complete, etc.<br/>
</p>
<p style="text-align: center;"><img width="466" height="275" src="http://www.jandrconsult.com/blogs/jeff/archives/images/tasklist.gif" alt="tasklist.gif"/></p>
<p>Tied with using a task list with four out of ten responses was finding time to work without interruptions. In Joel Spolsky's <a target="_blank" href="http://www.amazon.com/exec/obidos/tg/detail/-/1590593898/qid=1121525178/sr=8-1/ref=pd_bbs_1/104-7007618-5095932?v=glance&amp;s=books&amp;n=507846"><span style="font-style: italic;">Joel on Software</span></a> he writes, &quot;We all know that knowledge workers work best by getting into 'flow', also known as being 'in the zone', where they are fully concentrated on their work and fully tuned out of their environment. They lose track of time and produce great stuff through absolute concentration. This is when they get all of their productive work done. Writers, programmers, scientists, and even basketball players will tell you about being in the zone.&quot; In general, J&amp;R consultants get into the zone by working outside of normal business hours. Current customers may find this surprising, since when you call us we're always available. There are two tricks to being available. First, even if a consultant does not work during normal business hours, he is normally still at home, and therefore available to answer the phone. Second, many J&amp;R consultants work well over 40 hours a week, meaning that although they are working after business hours, many of them also work during business hours! The other response related to finding uninterrupted time to work was to eliminate distractions actively. This means more than simply looking for quite time, it means controlling the home environment so as not drain concentration from the present task.</p>
<p>The final two productivity tips were to create a &quot;real&quot; office at home and to take regular breaks. Creating a real office means that consultants pay for nice, comfortable office furniture rather than using the desk mom and dad gave them for their 13th birthday. Taking regular breaks may mean finding calming, thought-free activities around the house that allow for time to reorganize thoughts and clear the mind for especially complex tasks.</p>
<p>So if you visit the home office of a random J&amp;R Consultant, you will likely find a &quot;real&quot; office with comfortable furniture, a task list that has been prioritized and broken down into sub-tasks, and a distraction-free environment that allows the consultant to work without interruption.</p>
<p>And coffee. That's my one and only tip for both technology and productivity and health and sanity and long life: lots and lots of coffee.</p>]]>
    </content>
</entry>
<entry>
    <title><![CDATA[J &amp; R Technical Tips]]></title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/06/jr_technical_ti.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=66" title="J &amp;amp; R Technical Tips" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.66</id>

    <published>2005-06-25T00:00:29Z</published>
    <updated>2005-09-25T18:12:21Z</updated>

    <summary><![CDATA[As you may know, J&amp;R Consulting, Inc. is a group of intelligent and hard-working technologists and pedagogues dedicated to reliably directing and completing Herculean tasks with aplomb. (Picture here the author smirking: a futile attempt at humor.) &quot;How,&quot; you might wonder, &quot;does a group of people spread all over the eastern U.S. accomplish such a thing?&quot; I have wondered the same on more than one occasion. (I assure you that we do accomplish things. Now&rsquo;s your chance to chime in, J&amp;R customers reading this article!) To divine the answer, I asked everyone at J&amp;R the same two questions, &quot;What technology makes your work most efficient?&quot; and &quot;What productivity habits do you use regularly?&quot; In this article, I will focus on the technical tips that keep our consultancy running smoothly....]]></summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="General Computing" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>As you may know, J&amp;R Consulting, Inc. is a group of intelligent and hard-working technologists and pedagogues dedicated to reliably directing and completing Herculean tasks with aplomb. (Picture here the author smirking: a futile attempt at humor.) &quot;How,&quot; you might wonder, &quot;does a group of people spread all over the eastern U.S. accomplish such a thing?&quot; I have wondered the same on more than one occasion. (I assure you that we do accomplish things. Now&rsquo;s your chance to chime in, J&amp;R customers reading this article!) To divine the answer, I asked everyone at J&amp;R the same two questions, &quot;What technology makes your work most efficient?&quot; and &quot;What productivity habits do you use regularly?&quot; In this article, I will focus on the technical tips that keep our consultancy running smoothly.</p>]]>
        <![CDATA[<p>The most frequently identified pieces of technology used to improve efficiency were a software program called Groove Virtual Office, and the use of multiple computer monitors. Out of 12 responses for primary and secondary technology tips, these recommendations tied for first place and comprised two-thirds of all responses.</p>
<p><img width="300" hspace="5" height="317" border="0" align="right" alt="Groove Virtual Office" src="http://www.jandrconsult.com/blogs/jeff/archives/images/Groove-KB.jpg"/><a href="http://www.groove.net" target="_blank">Groove Virtual Office</a> is a tightly bound collection of software tools that allows all members of a team to see and interact with the same documents, lists, and records. For example, our main J&amp;R workspace currently includes the following tools: Files, Calendar, Discussion, Tasklist, Knowledge Base, Training Records, Corporate Policies, Media Repository, Mission Statement, and <a onclick="window.open('http://www.jandrconsult.com/blogs/jeff/archives/images%2FGroove-Pictures.shtml','popup','width=630,height=607,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false" href="http://www.jandrconsult.com/blogs/jeff/archives/images%2FGroove-Pictures.shtml">Pictures</a>. Similar to a corporate intranet, each of these tools contain files and records that are particularly relevant to some aspect of our business; however, that is where the similarities end. The most notable difference is that all of the files and records that are available when connected to the Internet (and other users) are also available when a network is unavailable, like on the airplane that is my current office. I would estimate that each J&amp;R person has five to seven discrete Groove workspaces in which they participate.</p>
<p>The use of multiple monitors connected to one or more computers was a technology tip that surprised me. I must admit that I have a single monitor, and was astounded to discover that more than half of my co-workers not only use multiple monitors, but also claim that it is a very important part of the work environment. When connected to one computer, the native operating system is frequently allowed to handle the desktop. When connected to multiple computers, a program called Synergy is frequently used to manage the monitors. Rob did a good job introducing <a href="http://www.jandrconsult.com/blogs/rob/archives/2005/02/leveraging_comp.shtml" target="_blank">Synergy</a>, so I will not reiterate its benefits.</p>
<p>The last two technology tips were a software program called Microsoft OneNote, and having adequately equipped computing resources.</p>
<img width="300" hspace="5" height="212" align="left" alt="Microsoft OneNote 2003" src="http://www.jandrconsult.com/blogs/jeff/archives/images/OneNote.jpg"/>
<p><a href="http://office.microsoft.com/en-us/FX010858031033.aspx" target="_blank">OneNote</a> is an electronic notebook program, and is a new addition to the Microsoft Office suite and Microsoft SharePoint services. Picture a stack of legal notebooks, each clearly tabbed by category and topic. Now imagine that stack of data being stored electronically; this gives you an idea of OneNote&rsquo;s power to organize your life. One of the best uses of OneNote I've seen is conducting meetings with all users connected to a shared notebook. When used in this manner, every user can add, remove, or modify text on the fly. I find this very useful, since I'm more apt to thoroughly understand meeting minutes if I can see them being created during the meeting than if I browse them (usually several days) after the meeting is conducted.</p>
<p>Having adequately equipped computing resources was also recognized as being important, especially having a computer with enough memory, a fast enough CPU, and a broadband cable connection. I agree with each of these, and regularly replace my core computer system every 18 months or so. This is even relatively cost effective if you are able to create and maintain your own system from individual parts. In my opinion, this usually beats the heck our of any service contract I have had to deal with.</p>
<p>Well, there you have it: Groove and OneNote for application productivity, and multiple monitors connected to well-equipped computers; these are the J&amp;R greatest hits for technical efficiency.</p>]]>
    </content>
</entry>
<entry>
    <title>Why Structure?</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/06/why_structure.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=64" title="Why Structure?" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.64</id>

    <published>2005-06-20T17:08:26Z</published>
    <updated>2005-09-25T18:12:21Z</updated>

    <summary><![CDATA[Did you know that all J&amp;R consultants write PL/SQL code identically? In fact, new employees are told to mimic the style of any other senior consultant. I remember once asking a java developer from another company to use a specific standard for object and variable nomenclature. You would have thought I asked him to slap his mother. But this article isn&rsquo;t just about coding, it&rsquo;s about implementing structure in general. Succinctly, why do I use structure?...]]></summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="General Consulting" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>Did you know that all J&amp;R consultants write PL/SQL code identically? In fact, new employees are told to mimic the style of any other senior consultant. I remember once asking a java developer from another company to use a specific standard for object and variable nomenclature. You would have thought I asked him to slap his mother. But this article isn&rsquo;t just about coding, it&rsquo;s about implementing structure in general. Succinctly, why do I use structure?</p>]]>
        <![CDATA[<p>In 1990 I was working as a part-time bookseller in a Waldenbooks located in Midtown Plaza, Rochester, NY. Midtown is located under the Xerox building, which was at the time Xerox world headquarters, so we had steady, regular business. By 1992, I was made manager of the store, and I thought things were going very well. I had a staff of 8-14 people, and because of our location, we had high volume per square foot sales figures. Then something odd happened: Waldenbooks corporate headquarters told us that some consulting company would be implementing changes to the way we did business. From what I could tell, the plan was to implement a tighter inventory turnaround and further standardize business operations. Actually, they would tell us <em>how</em> to do business &ndash; <em>precisely how</em>! Let me give just one example: we had to locate space on a shelf and using special tape, make a little square. The square was labeled, &quot;Tape&quot;. In that square was placed &ndash; you guessed it &ndash; the boxing tape! If the tape was placed anywhere else I would get the evil eye from my district manager. &quot;Are you kidding me? I, the manager of a store that did more than a million dollars of business annually, was being told where to put the boxing tape?&quot; I seriously considered quitting.</p>
<p>About two weeks later I noticed something: I could always find the tape. You see, in a bookstore, you can rarely find the boxing tape. The reason that you can never find the tape is because it is used constantly, so it's a moving target. But because you can never find the boxing tape, the staff keeps exactly 47 rolls of boxing tape stashed around the backroom and behind the cash register. So, it&rsquo;s not just one roll you cannot find, its 47 rolls you cannot find. After following the consultants' advice, I could find the boxing tape (and the 46 remaining rolls, which we stashed in a hidden cabinet so as to not confuse the district manager when she did inspections). This was my first contact with the franchise phenomenon, and coincidentally, my first contact with consultants.</p>
<iframe align="right" marginwidth="0" hspace="6" vspace="6" marginheight="0" src="http://rcm.amazon.com/e/cm?t=jrconsinc-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0553246984&amp;fc1=000000&amp;=1&amp;lc1=0000ff&amp;bc1=000000&amp;lt1=_blank&amp;IS2=1&amp;f=ifr&amp;bg1=ffffff&amp;f=ifr" frameborder="0" width="120" scrolling="no" height="240"></iframe>
<p>In &quot;The Third Wave&quot;, Alvin Toffler states, &quot;Individuals need life structure. A life lacking in comprehensive structure is an aimless wreck. The absence of structure breeds breakdown. Structure provides the relatively fixed points of reference we need.&quot; I believe this quote because it rings true. I am a person that needs structure, but more importantly, I believe it improves my ability to do quality work. I know people who do not use structure this way, and most of them have expressed to me the desire to start. Yet, when it comes to certain aspects of life or work, most people I know are extremely resistant to using structure.</p>
<p>(Notice that I say &quot;using&quot; structure, not &quot;being&quot; structured. Structure is something a person does, not who they are. Granted, some people enjoy a structured environment, but for all of us, it is a task.)</p>
<p>Here are some of the reasons I use structure in my work:</p>
<ul>
    <li><em>Organizing my tasks</em> keeps my mind free of clutter. Consider a desk covered with PostIt notes; that is what my mind feels like when I have not organized my work. I suppose the person who uses PostIt notes must pat themselves on the back for having tasks written down. That&rsquo;s a start, I suppose. </li>
    <li><em>Organizing my workspace</em> keeps my electronic desk free of clutter. My file system is organized by customer and geographic location, project and stage of work. Rather than spending time searching for documents in strange locations with strange names, I choose to spend my time at the beginning of the task organizing my workspace, so that documents are always placed where I expect to find them. </li>
    <li><em>Prioritizing tasks</em> keeps bosses and customers happy with my turn-around time. I find that doing tasks in order of priority allows me to complete all tasks within a period that is acceptable to each task. Spreading a task out over 3 months is completely acceptable if the task is scheduled for completion in 5 months. I try to ignore what I want to do, and focus on what my customers and boss wish me to complete. </li>
    <li>Using <em>repetitive actions</em> increases accuracy. For example, if I&rsquo;m writing an important lifecycle document, I immediately save it with the proper document name and designation, and check it into the document repository. This guarantees that if I update the document in the future that the repository software will visually remind me that the document must be updated. </li>
    <li>Using <em>document and code templates</em> increases the readability and consistency across multiple documents and multiple consultants. I find that having consistent document and code structures speeds the development of documents and the maintenance of code. </li>
</ul>
<p>It may seem that I spend a lot of time organizing; nothing could be further from the truth. I find that having an organized workspace is the simplest thing in the world, and once begun, requires almost no additional time.</p>
<p>At some point in the future I intend to explore how a small consultancy might implement franchising-like paradigms to run the business.</p>]]>
    </content>
</entry>
<entry>
    <title>Java Monitors in SQL*LIMS 4.1</title>
    <link rel="alternate" type="text/html" href="http://www.jandrconsult.com/blogs/jeff/archives/2005/06/java_monitors_i.shtml" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.jandrconsult.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=3/entry_id=60" title="Java Monitors in SQL*LIMS 4.1" />
    <id>tag:www.jandrconsult.com,2005:/blogs/jeff//3.60</id>

    <published>2005-06-09T22:53:56Z</published>
    <updated>2005-09-25T18:12:21Z</updated>

    <summary>Java is a language that has gained much popularity. This is partially due to its ability to run on most computing platforms. However, if you try to run a java program as a Windows monitor on the application tier of a SQL*LIMS version 4.1 installation, you will notice that it doesn&apos;t seem to work. In this article, I&apos;ll demonstrate how to run a java program as a Windows service using a helper program already delivered with the SQL*LIMS software....</summary>
    <author>
        <name>Jeff Vannest</name>
        <uri>http://www.jandrconsult.com/blogs/jeff</uri>
    </author>
            <category term="LIMS Software" />
    
    <content type="html" xml:lang="en" xml:base="http://www.jandrconsult.com/blogs/jeff/">
        <![CDATA[<p>Java is a language that has gained much popularity. This is partially due to its ability to run on most computing platforms. However, if you try to run a java program as a Windows monitor on the application tier of a SQL*LIMS version 4.1 installation, you will notice that it doesn't seem to work. In this article, I'll demonstrate how to run a java program as a Windows service using a helper program already delivered with the SQL*LIMS software.</p>]]>
        <![CDATA[<p>There are at least two ways a program written in java can run as a Windows service. I will describe the first method, although it is not the one I recommend: The java program can be compiled into a Windows native executable. While this is functional, it typically requires an expensive development suite like <a href="http://www.borland.com/us/products/jbuilder/index.html" target="_blank">Borland JBuilder Enterprise Edition</a>, and it means that if you intend to use the same java program on multiple computing environments, you'll have to re-test and re-validate each OS executable that you produce. Further, it means that future modifications also require an expensive development suite. Unless there is compelling reason, I do not recommend this method.<br/>
<br/>
The method I prefer is to use a helper program delivered with SQL*LIMS. Using this method keeps the java files in their original form, and works just as effectively. From the SQL*LIMS server CD, locate the file named srunner.exe. Next, create three text files as follows:<br/>
<br/>
File #1: create_service.bat<br/>
<br/>
&nbsp;&nbsp;&nbsp; @echo off<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO This file is used to create a Windows service using<br/>
&nbsp;&nbsp;&nbsp; ECHO a serviceprops file and srunner.exe, which is used to<br/>
&nbsp;&nbsp;&nbsp; ECHO install, remove, and run the program as a Windows service.<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; SET /P serviceprop=Enter service properties file:<br/>
&nbsp;&nbsp;&nbsp; .\srunner %serviceprop%<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO Installation complete.<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; PAUSE<br/>
<br/>
File #2 remove_service.bat<br/>
<br/>
&nbsp;&nbsp;&nbsp; @echo off<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO This file is used to delete a service using its internal<br/>
&nbsp;&nbsp;&nbsp; ECHO Windows service name. This name may not be the one displayed<br/>
&nbsp;&nbsp;&nbsp; ECHO in the Services dialog.<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; SET /P serviceprop=Enter service name:<br/>
&nbsp;&nbsp;&nbsp; .\srunner -r %serviceprop%<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; ECHO Removal complete.<br/>
&nbsp;&nbsp;&nbsp; ECHO .<br/>
&nbsp;&nbsp;&nbsp; PAUSE<br/>
<br/>
File #3 service.serviceprops<br/>
<br/>
&nbsp;&nbsp;&nbsp; My_Monitor<br/>
&nbsp;&nbsp;&nbsp; My Monitor<br/>
&nbsp;&nbsp;&nbsp; Manual<br/>
<br/>
&nbsp;&nbsp;&nbsp; java<br/>
&nbsp;&nbsp;&nbsp; -cp .;.\myJar.jar com.my.company.myClass<br/>
&nbsp;&nbsp;&nbsp; C:\sqllimssvr\v4_1_0\myMonitor\Bin<br/>
&nbsp;&nbsp;&nbsp; &lt;END&gt;<br/>
<br/>
The first two batch files are self explanatory; they are used to create and remove your new monitor, which is being installed as a Windows service. The first batch file will prompt for a filename, which is the name of File #3. The second batch file fill prompts for the internal name of the Windows service to remove. Both files should be executed with the Windows Services dialog closed, since Windows is quirky about adding and removing services with it open.<br/>
<br/>
The third file bears some explanation, for this is where you're going enter the information about your new monitor. Here's a version of the file with line numbers:<br/>
<br/>
&nbsp;&nbsp; 1. My_Monitor<br/>
&nbsp;&nbsp; 2. My Monitor<br/>
&nbsp;&nbsp; 3. Manual<br/>
&nbsp;&nbsp; 4.<br/>
&nbsp;&nbsp; 5. java<br/>
&nbsp;&nbsp; 6. -cp .;.\myJar.jar com.my.company.myClass<br/>
&nbsp;&nbsp; 7. C:\sqllimssvr\v4_1_0\myMonitor\Bin<br/>
&nbsp;&nbsp; 8. &lt;END&gt;<br/>
<br/>
Line number 1 is the internal name of the WIndows service, and must contain no spaces.<br/>
<br/>
Line number 2 is the external name of the Windows service, the one you see in the Services dialog.<br/>
<br/>
Line number 3 indicates how the service will start, and the options are Manual, Automatic, and Disabled.<br/>
<br/>
Line number 4 can be left blank. If there is a service upon which your new monitor depends, you can enter its internal Windows service name, otherwise, just leave line 4 blank.<br/>
<br/>
Line 5 is the name of the command to execute, which in this case is the java virtual machine. Specifying &quot;java&quot; all by itself will choose whichever JVM is the system default. If you wish a specific JVM to execute - for example, your new monitor is only validated on java version 1.3.1 - then you can specify the full path name to the java.exe program.<br/>
<br/>
Line 6 lists all of the parameters you wish to send to the java program. In this example, I have specified a java classpath pointing to the current directory and to a jar file named myJar.jar. The next parameter indicates that I wish to start the execution of the &quot;myClass&quot; class in the &quot;com.my.company&quot; package.<br/>
<br/>
Line 7 indicates the folder from which the Windows service will execute, which in this example, is a custom Bin folder off the SQL*LIMS server folder.<br/>
<br/>
Line 8 must have a single word, &quot;&lt;END&gt;&quot;, indicating the end of the file.<br/>
<br/>
Once you have configured the service.serviceprops file, simply execute the create_service.bat, and your new monitor will run as a Windows service.<br/>
<br/>
By the way, if you do not have access to the SQL*LIMS server CD and the srunner.exe program, you can download a similar program from the same author at the KC Multimedia and Design Group's page for &quot;<a target="_blank" href="http://www.kcmultimedia.com/javaserv/#Download">Running a Java 2 Application as an NT Service</a>&quot;.<br/>
</p>]]>
    </content>
</entry>

</feed>

