• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: How can I stream blobs to/from entities?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How can I stream blobs to/from entities?


  • Subject: Re: How can I stream blobs to/from entities?
  • From: Paolo Sommaruga <email@hidden>
  • Date: Wed, 14 Apr 2004 19:35:52 +0200

Hi Serge,

thanks for your feedback. I am rather interested on upload of large
blob by means of a JC. After that I have transferred the file from the
client side to the server side I tryied with the following remote
method in order to avoid the NSData use for memory saving (thanks to
Jonathan Rochkind for the hint how to get a JDBCContext)

	public void clientSideRequestSaveDocument(String filename) {

		EOObjectStoreCoordinator rootStore = null;
		try {
			Integer elementId = singleIntegerPrimaryKeyForObject(this);		//
thanks to WOCode.com
			File f = new File("/tmp/" + filename); 	// assume the file is
already in the server
			int size = (int) f.length();
			FileInputStream fin = new FileInputStream("/tmp/" + filename);
			EOFetchSpecification fs = new
EOFetchSpecification("ElementoSemplice", null, null);
			rootStore = (EOObjectStoreCoordinator)
editingContext().rootObjectStore();
			rootStore.lock();
			EODatabaseContext dbContext = (EODatabaseContext)
rootStore.objectStoreForFetchSpecification(fs);
			EOAdaptor adaptor = dbContext.database().adaptor();
			EOAdaptorContext adContext = dbContext.adaptorContext();
			JDBCContext jcontext = (JDBCContext) adContext;
			Connection con = jcontext.connection();
			PreparedStatement pstmt = con.prepareStatement("update Elemento set
docfile=? where element_id=?");
			pstmt.setInt(2, elementId.intValue());
			pstmt.setBinaryStream(1, fin, size);
			pstmt.executeUpdate();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		finally {
			 rootStore.unlock();
		}
	}

The code works very well but only with file < 3MB size. With greater
size I need to increase the max jvm heap size. I can upload a file of
10 MB size only with -Xmx512m, which is too much memory for a single WO
instance for me

This is exactly the same behaviour which I have experimented with a
traditional code that use NSData, like

		     NSData resultData;	// assume exists

		      editingContext().lock();
			takeValueForKey(resultData, "docfile");
			editingContext().saveChanges();
			editingContext().unlock();

I had hoped that working directly at JDBC level the needed memory
amount would decrease. Instead the two codes seems actually to have the
same memory behaviour.

Is this a JDBC driver or a database issue ? I have tested with
PostgreSQL 7.4.1

Maybe some EO guru can give me some hint

Regards


	Paolo Sommaruga



Il giorno 13/apr/04, alle 21:03, Serge Froment ha scritto:

> Hi Paolo,
>
> I have some code that works for me. Since it uses undocumented API, I
> can't garantee it works in all cases, though. A safer method would be
> to ignore WebObjects' database connections and create your own pool of
> JDBC connections.
>
> Anyway, here is a class SFGenericRecord
> (Stream-Friendly-Generic-Record) that implements a protected method
> blobValueForKey. This method fetches the database at JDBC level using
> WebObjects's existing connection and returns a java.sql.Blob.
>
> To use it:
>
> 1. Add the SFGenericRecord class to your project.
> 2. Derive you EOF class from SFGenericRecord instead of
> EOGenericRecord.
> 3. Don't mark your blob attribute as a class property (so that EOF will
> not fetch it).
> 4. Create an accessor that calls blobValueForKey (from superclass
> SFGenericRecord).
>
> To stream the blob to a WOResponse:
>
> Assume "build" is a EO instance that derives from SFGenericRecord and
> has an accessor outputFileData that calls
> blobValueForKey("outputFileData"):
>
> Blob blob = build.outputFileData();
> WOResponse response = new WOResponse();
> response.setHeader("data/binary", "Content-Type");
> response.setHeader("attachment;filename=" + build.outputFileName(),
> "Content-Disposition");
> response.setContentStream(blob.getBinaryStream(), 4096, (int)
> blob.length());
> return response;
>
> And now, the SFGenericRecord class:
>
> // Stream-Friendly subclass of EOGenericRecord
> public class SFGenericRecord extends EOGenericRecord
> {
> 	// constructors
> 	public SFGenericRecord()
> 	{
> 		super();
> 	}
> 	public SFGenericRecord(EOClassDescription classDescription)
> 	{
> 		super(classDescription);
> 	}
>
> 	// fetch a database blob using JDBC
> 	protected Blob storedBlobForKey(String key)
> 	{
> 		EOEntity entity =
> ((EOEntityClassDescription)classDescription()).entity();
> 		EODatabaseContext databaseContext =
> EODatabaseContext.registeredDatabaseContextForModel(entity.model(),
> editingContext());
> 		databaseContext.lock();
> 		try
> 		{
> 			return getBlob(entity, databaseContext, key);
> 		}
> 		catch (Exception e1)
> 		{
> 			if (databaseContext._isDroppedConnectionException(e1))
> 			{
> 				try
> 				{
> 					databaseContext.database().handleDroppedConnection();
> 					return getBlob(entity, databaseContext, key);
> 				}
> 				catch (Exception e2)
> 				{
> 					throw new NSForwardException(e2);
> 				}
> 			}
> 			else
> 				throw new NSForwardException(e1);
> 		}
> 		finally
> 		{
> 			databaseContext.unlock();
> 		}
> 	}
>
> 	// actual fetching for blob accessor
> 	private Blob getBlob(EOEntity entity, EODatabaseContext
> databaseContext, String key)
> 		throws SQLException
> 	{
> 		String attributeColumnName = entity.attributeNamed(key).columnName();
> 		StringBuffer query = new StringBuffer();
> 		query.append("SELECT ");
> 		query.append(attributeColumnName);
> 		query.append(" FROM ");
> 		query.append(entity.externalName());
> 		query.append(" WHERE ");
> 		NSDictionary primaryKey =
> EOUtilities.primaryKeyForObject(editingContext(), this);
> 		Enumeration attributeNames = primaryKey.allKeys().objectEnumerator();
> 		while (attributeNames.hasMoreElements())
> 		{
> 			String attributeName = (String) attributeNames.nextElement();
> 			query.append(entity.attributeNamed(attributeName).columnName());
> 			query.append(" = ");
> 			query.append(primaryKey.valueForKey(attributeName));
> 			if (attributeNames.hasMoreElements())
> 				query.append(" AND ");
> 		}
>          EODatabaseChannel databaseChannel =
> databaseContext.availableChannel();
>          EOAdaptorChannel adaptorChannel =
> databaseChannel.adaptorChannel();
>          if(!adaptorChannel.isOpen())
>              adaptorChannel.openChannel();
> 		Connection connection =
> ((JDBCContext)adaptorChannel.adaptorContext()).connection();
> 		Statement statement = connection.createStatement();
> 		ResultSet resultSet = statement.executeQuery(query.toString());
> 		if (resultSet.next())
> 			return resultSet.getBlob(attributeColumnName);
> 		else
> 			throw new SQLException("No record for query " + query);
> 	}
> }
>
> Le 13 avr. 04, ` 10:58, Paolo Sommaruga a icrit :
>
>> metto I have the same problema. Have you reached the WO JDBC
>> connection ?
>>
>
> Serge Froment
> http://www.serge-froment.com
> _______________________________________________
> webobjects-dev mailing list | email@hidden
> Help/Unsubscribe/Archives:
> http://www.lists.apple.com/mailman/listinfo/webobjects-dev
> Do not post admin requests to the list. They will be ignored.
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.


  • Follow-Ups:
    • Re: How can I stream blobs to/from entities?
      • From: Arturo PĂ©rez <email@hidden>
References: 
 >How can I stream blobs to/from entities? (From: Serge Froment <email@hidden>)
 >Re: How can I stream blobs to/from entities? (From: Jonathan Rochkind <email@hidden>)
 >Re: How can I stream blobs to/from entities? (From: Serge Froment <email@hidden>)
 >Re: How can I stream blobs to/from entities? (From: Serge Froment <email@hidden>)

  • Prev by Date: Re: NSString comparisons
  • Next by Date: deployment - quick questions
  • Previous by thread: Re: How can I stream blobs to/from entities?
  • Next by thread: Re: How can I stream blobs to/from entities?
  • Index(es):
    • Date
    • Thread