This discussion is archived
8 Replies Latest reply: Oct 24, 2003 10:38 AM by 307050 RSS

messageFileUpload doesn't work

steve.west Newbie
Currently Being Moderated
Hi,
I am trying to load Word documents into a BLOB column using UIX & BC4J. I have added a BC4J:messageFileUpload column to my form and it runs OK, with a button generated to capture the file name. However when I try and commit the new record, I get the following error messge generated:

JBO-25009: Cannot create an object of type:oracle.jbo.domain.BlobDomain with value:"C:\Temp\32514.doc"

My column is defined as:

<bc4j:messageFileUpload prompt="Upload the Agreement Document"
name="AgrDoc" attrName="AgrDoc"/>

I have also added usesUpload="True" to my Form definition.

What am I doing wrong?


Thanks,

Steve
  • 1. Re: messageFileUpload doesn't work
    307050 Newbie
    Currently Being Moderated
    Steve,

    What does your event handler code do to pass along the value from the file upload into the BC4J row?

    -brian
    UIX Team
  • 2. Re: messageFileUpload doesn't work
    steve.west Newbie
    Currently Being Moderated
    Brian,

    My event handler does nothing - can you give me an example please?


    Steve
  • 3. Re: messageFileUpload doesn't work
    307050 Newbie
    Currently Being Moderated
    Steve,

    Are you using the BC4J Intermedia domain types? (What is the type of the entity object attribute you want to upload the file into?)

    I'm trying to work out an example of this.

    -brian
  • 4. Re: messageFileUpload doesn't work
    307050 Newbie
    Currently Being Moderated
    Sorry, I just realized your message referenced BlobDomain. Let me try to figure this out and get back to you.

    -brian
  • 5. Re: messageFileUpload doesn't work
    steve.west Newbie
    Currently Being Moderated
    Thanks Brian
  • 6. Re: messageFileUpload doesn't work
    307050 Newbie
    Currently Being Moderated
    Steve,

    I have done some research, and I've cooked up an example of how to do it. This is based on having a VO named Blobtest with a String "nameAttr" attribute and a BlobDomain "obj" attribute.

    First, you need to provide a PageBroker implementation that overrides the upload behavior to save the uploaded bytes. I saved them in memory, in the BajaContext, but you could save them anywhere you like (and leave yourself information in the return value of doUploadFile). See the docs for AbstractPageBroker.doUploadFile for more details.

    Then, in your event handler in the create page, instead of using bc4j:setAttribute to set the BLOB attribute, you use a custom method event handler to read the bytes, create a BLOB, and then set the obj attribute.

    Finally, you need to hook in your PageBroker via web.xml. Put something like this in web.xml in the definition of the UIX servlet:
    <init-param>      
      <param-name>oracle.cabo.servlet.pageBroker</param-name>
      <param-value>view.MyPageBroker</param-value>
    </init-param>
    The page broker code is below. For my convenience I put the event handler code here too, but that was an arbitrary decision to put all my Java code for this example in the one class, view.MyPageBroker.
    package view;
    import java.io.*;
    import oracle.cabo.servlet.*;
    import oracle.cabo.servlet.event.*;
    import oracle.cabo.servlet.xml.*;
    import oracle.cabo.share.util.*;
    import oracle.cabo.data.jbo.servlet.bind.*;
    import oracle.jbo.*;
    import oracle.cabo.share.util.*;
    import oracle.jbo.domain.*;
    import model.*;
    
    public class MyPageBroker extends UIXPageBroker 
    {
      public static EventResult saveUploadedFile(
        BajaContext context, 
        Page page, 
        PageEvent event) throws Throwable
      {
        Object uploadedItem = context.getProperty(_NS, _UPLOAD_KEY);
        if (! (uploadedItem instanceof byte[]))
        {
          throw new Exception("No uploaded bytes found");
        }
    
        BlobDomain blob = new BlobDomain((byte[]) uploadedItem);
        
        BlobtestViewRowImpl row = (BlobtestViewRowImpl) 
          ServletBindingUtils.getRow(context);
    
        row.setObj(blob);
        
        return null;
      }
    
      protected String doUploadFile(
        BajaContext context, 
        Page page, 
        MultipartFormItem item) throws IOException
      {
        if (item.getFilename() != null)
        {
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          item.writeFile(baos);
          context.setProperty(_NS, _UPLOAD_KEY, baos.toByteArray());
        }
    
        return item.getName();
      }
    
      private static final String _NS = "MyPageBroker";
      private static final Object _UPLOAD_KEY = new Object();
    }
    Finally, here's an example from my create UIX page of where to call this method event handler:
      <event name="apply" >
       <!-- using the ApplicationModule causes it to be checked out from the
            ApplicationPool.  It is released using stateful mode. -->
       <bc4j:findRootAppModule name="BlobtestView1AppModule" >
        <!-- establish the ViewObject scope -->
        <bc4j:findViewObject name="BlobtestView1" >
         <!-- find the row by key, falling back on a new default 
              row if the key is not found -->
          <bc4j:findRow name="CreateBlobtestView1" >
          <!-- sets the current row -->
          <bc4j:setPageProperty name="key" >
            <bc4j:stringKey />
          </bc4j:setPageProperty>
    
          <!-- set each attribute explicitly -->
          <bc4j:setAttribute name="NameAttr" />
    
          <!-- capture uploaded file using custom method event handler -->
          <method class="view.MyPageBroker" method="saveUploadedFil" />
          
          <!-- insert the current row into the ViewObject -->
          <bc4j:insertRow/>
          <!-- commit the transaction -->
          <bc4j:commit/>
          <bc4j:executeQuery/>
          <!-- forward to the summary page -->
          <ctrl:go name="BlobtestView1_View" redirect="true" />
         </bc4j:findRow>
        </bc4j:findViewObject>
       </bc4j:findRootAppModule>
      </event>
    Hope this helps. I certainly agree this is not easy to figure out!

    -brian
    UIX Team
  • 7. Re: messageFileUpload doesn't work
    steve.west Newbie
    Currently Being Moderated
    Thanks Brian, I'll give it a try. It doesn't seem very intuitive, I thought the UIXml BC4J frameworks were supposed to take a lot of this type of low-level coding away.

    How did you find this out, is it documented anywhere that I missed, or is it internal to Oracle? Can we have access to some more UIX BC4J examples? There is plenty on Struts BC4J (Toystore) but very little on UIX. The UIX demos contain no BC4J!!


    Thanks,


    Steve
  • 8. Re: messageFileUpload doesn't work
    307050 Newbie
    Currently Being Moderated
    Steve,

    I certainly appreciate your frustration. Both UIX and BC4J are high level frameworks that each raise the level of abstraction in their given functional areas, web-based UI and data access respectively. The integration between the two in 9.0.3 provides a number of simple, declarative hooks that, when they are sufficient, substantially simplify making database/web applications.

    However, when you reach points where that integration does not have a pre-canned answer (like the file upload case you mentioned here), the solution often requires some relatively detailed work using both the UIX and the BC4J APIs. In this particular case, what I did was look at the UIX documentation and JavaDoc for how to handle the file upload (to save the uploaded bytes). Then I used the UIX/BC4J integration docs to find out how to get access to the current Row in my custom method event handler. Finally, I used to BC4J JavaDoc (and code insight) to find out how to create the BlobDomain and set it on my row.

    One thing to point out here (I perhaps should have mentioned before instead of just alluding to it by asking about what domain you were using) is that the BC4J/UIX integration does have specific support for Intermedia types in the database with automatic support for uploading files. I don't know anything about Intermedia, so I don't know if using it is appropriate to your situation, but if it is, consult the UIX Developer's Guide chapter on "Media" (chapter after the BC4J chapter).
    Can we have access to some more UIX BC4J examples?
    The only 9.0.3 UIX/BC4J examples available are in the UIX 2.1.7 demo bundle, which is available at http://otn.oracle.com/software/products/ids/uix/index.html. Also, the output of the Complete Application Wizard is meant to help users first starting out with this integration.

    For JDeveloper 10g production, there will hopefully be more examples available showing integration of UIX with ADF data binding (which can be used with BC4J among other model technologies). Speaking of 10g and ADF, a goal for this new framework is to make integration amongst model, view and controller clearer and easier to use. I think it has come a long way, even in the preview release, and I certainly suggest checking it out if you have a chance.

    Hope this clarifies some. I'll try to get to your other questions soon. :)

    -brian
    UIX Team