Re: Lazy optional relationship creation on EO accessor
Re: Lazy optional relationship creation on EO accessor
- Subject: Re: Lazy optional relationship creation on EO accessor
- From: Kieran Kelleher <email@hidden>
- Date: Tue, 23 Feb 2010 13:17:40 -0500
Just throwing this out there into the mix of replies....... this is unaltered copy/paste from production code ..... YMMV ... (btw, the OptimisticLockAction makes sure that another thread does not create at the same time)
/**
* @return CTTextBlob lazily created textTemplate relationship. If
* mediaTemplate exists, this creates and saves the related initial
* object in an optimistic fashion.
*/
public CTTextBlob textTemplateAutoCreate() {
CTTextBlob textTemplate = super.textTemplateObject();
if (textTemplate == null) {
if (isNewObject()) {
textTemplate = CTTextBlob.createInstance(editingContext());
super.setTextTemplateObject(textTemplate);
} else {
// existing Object
final CTMediaTemplate t = this;
WKEOUtils.OptimisticLockAction action = new WKEOUtils.OptimisticLockAction() {
@Override
protected Object doPerform(EOEditingContext ec) {
CTMediaTemplate localTemplate = t.localInstanceIn(ec);
CTTextBlob textBlob = CTTextBlob.createInstance(ec);
localTemplate.setTextTemplateObject(textBlob);
ec.saveChanges();
return textBlob.localInstanceIn(t.editingContext());
};
};
try {
textTemplate = (CTTextBlob) action.perform(editingContext().rootObjectStore());
} catch (Exception e) {
throw new NestableRuntimeException(e);
}
} // ~ if (isNewObject())
}
return textTemplate;
}
FYI, here is the OptimisticLockAction utility code......
/**
* Deals with the nitty-gritty of a critical <strong>short-running</strong>
* task where we depend on optimistic locking to guarantee that another
* process does not change optimistic locking attributes at the same time. To
* understand why this is necessary, read this:
* {@link http://terminalapp.net/dr-optimistic-locking/}.
*
* Wraps the actions in
* appropriate locks. WARNING: The OSC is locked for the period of the
* transaction. All EOF access on this OSC is blocked. Do not use this for
* actions that take more than a few milliseconds on OSC's that are being
* used by request threads!
*
* Code design inspired by {@link ERXEOAccessUtilities.ChannelAction}
*
* Example of usage
*
* <pre>
* OptimisticLockAction action = new WKEOUtils.OptimisticLockAction() {
* @Override
* protected Object doPerform(EOEditingContext actionEditingContext) {
* CTCampaign localCampaign = (CTCampaign) actionEditingContext.faultForGlobalID(gid, actionEditingContext);
* try {
* // Ship it
* localCampaign.shipMessages();
* actionEditingContext.saveChanges();
* } catch (EOGeneralAdaptorException e) {
* String additionalInfo = WKEOUtils.generalAdaptorExceptionInfo(e);
* log.error("Failed to ship campaign " + localCampaign + ". Probably another instance was sending "
* + "this campaign to the production mail queueat the same time; AdditionalInfo: "
* + additionalInfo, e);
* }
* return null;
* }
* };
*
* try {
* action.perform(parentObjectStore());
* } catch (Exception e) {
* throw new RuntimeException(e);
* }
* </pre>
*
* @author kieran
*/
public static abstract class OptimisticLockAction {
/**
* This method is called in a new locked editing context that has been
* created in the osc passed in. Perform your changes in this editing
* context. Any errors will be thrown. Return any result you want.
*
* @param osc
*/
protected abstract Object doPerform(EOEditingContext ec);
public Object perform() throws Exception {
return perform(null);
}
/**
* @param osc
* the root object store to be locked so that true optimistic
* locking can be enforced.
* @return the result of your doPerform method implementation
* @throws Exception
*/
public Object perform(EOObjectStore osc) throws Exception {
osc.lock();
try {
EOEditingContext ec = WKEOUtils.newManualLockingEditingContext(osc);
ec.lock();
try {
// Don't use stale EO's to begin with
ec.setFetchTimestamp(System.currentTimeMillis());
return doPerform(ec);
} catch (Exception e) {
throw e;
} finally {
ec.unlock();
ec.dispose();
}
} catch (Exception e) {
throw e;
} finally {
osc.unlock();
}
}
}
On Feb 23, 2010, at 11:55 AM, Jon Nolan wrote:
> Is this sane and safe?
>
> public Properties properties() {
> Properties properties = super.properties();
> if (properties == null) {
> properties = Properties.createProperties(editingContext());
> setPropertiesRelationship(properties);
> }
> return properties;
> }
>
> Seems to work fine and suits my needs perfectly but it makes me uneasy.
>
> Thanks,
> Jon
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden