use of org.datanucleus.exceptions.NucleusObjectNotFoundException in project datanucleus-core by datanucleus.
the class ReachabilityAtCommitHandler method execute.
/**
* Method to perform the "persistence-by-reachability" at commit.
*/
public void execute() {
try {
this.executing = true;
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010032"));
}
// from makePersistent in this txn, or enlisted existing objects) then run reachability checks
if (!persistedIds.isEmpty() && !flushedNewIds.isEmpty()) {
Set currentReachables = new HashSet();
// Run "reachability" on all known persistent objects for this txn
Object[] ids = persistedIds.toArray();
Set objectNotFound = new HashSet();
for (int i = 0; i < ids.length; i++) {
if (!deletedIds.contains(ids[i])) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug("Performing reachability algorithm on object with id \"" + ids[i] + "\"");
}
try {
ObjectProvider op = ec.findObjectProvider(ec.findObject(ids[i], true, true, null));
if (!op.isDeleted() && !currentReachables.contains(ids[i])) {
// Make sure all of its relation fields are loaded before continuing. Is this necessary, since its enlisted?
op.loadUnloadedRelationFields();
// Add this object id since not yet reached
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007000", StringUtils.toJVMIDString(op.getObject()), ids[i], op.getLifecycleState()));
}
currentReachables.add(ids[i]);
// Go through all relation fields using ReachabilityFieldManager
ReachabilityFieldManager pcFM = new ReachabilityFieldManager(op, currentReachables);
int[] relationFieldNums = op.getClassMetaData().getRelationMemberPositions(ec.getClassLoaderResolver());
if (relationFieldNums != null && relationFieldNums.length > 0) {
op.provideFields(relationFieldNums, pcFM);
}
}
} catch (NucleusObjectNotFoundException ex) {
objectNotFound.add(ids[i]);
}
} else {
// Was deleted earlier so ignore
}
}
// Remove any of the "reachable" instances that are no longer "reachable"
flushedNewIds.removeAll(currentReachables);
Object[] nonReachableIds = flushedNewIds.toArray();
if (nonReachableIds != null && nonReachableIds.length > 0) {
// TODO See CORE-3276 for a possible change to this
for (int i = 0; i < nonReachableIds.length; i++) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010033", nonReachableIds[i]));
}
try {
if (!objectNotFound.contains(nonReachableIds[i])) {
ObjectProvider op = ec.findObjectProvider(ec.findObject(nonReachableIds[i], true, true, null));
if (!op.getLifecycleState().isDeleted() && !ec.getApiAdapter().isDetached(op.getObject())) {
// Null any relationships for relation fields of this object
op.replaceFields(op.getClassMetaData().getNonPKMemberPositions(), new NullifyRelationFieldManager(op));
ec.flush();
}
}
} catch (NucleusObjectNotFoundException ex) {
// just ignore if the object does not exist anymore
}
}
// B). Remove the objects
for (int i = 0; i < nonReachableIds.length; i++) {
try {
if (!objectNotFound.contains(nonReachableIds[i])) {
ObjectProvider op = ec.findObjectProvider(ec.findObject(nonReachableIds[i], true, true, null));
op.deletePersistent();
}
} catch (NucleusObjectNotFoundException ex) {
// just ignore if the file does not exist anymore
}
}
}
// Make sure any updates are flushed
ec.flushInternal(true);
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010034"));
}
} finally {
this.executing = false;
}
}
use of org.datanucleus.exceptions.NucleusObjectNotFoundException in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method performDetachAllOnTxnEndPreparation.
/**
* Method to perform all necessary preparation for detach-all-on-commit/detach-all-on-rollback.
* Identifies all objects affected and makes sure that all fetch plan fields are loaded.
*/
private void performDetachAllOnTxnEndPreparation() {
// JDO spec 12.7.3 "Root instances"
// "Root instances are parameter instances for retrieve, detachCopy, and refresh; result
// instances for queries. Root instances for DetachAllOnCommit are defined explicitly by
// the user via the FetchPlan property DetachmentRoots or DetachmentRootClasses.
// If not set explicitly, the detachment roots consist of the union of all root instances of
// methods executed since the last commit or rollback."
Collection<ObjectProvider> ops = new ArrayList<>();
Collection roots = fetchPlan.getDetachmentRoots();
Class[] rootClasses = fetchPlan.getDetachmentRootClasses();
if (roots != null && !roots.isEmpty()) {
// Detachment roots specified
for (Object root : roots) {
ops.add(findObjectProvider(root));
}
} else if (rootClasses != null && rootClasses.length > 0) {
// Detachment root classes specified
ObjectProvider[] txOPs = enlistedOPCache.values().toArray(new ObjectProvider[enlistedOPCache.size()]);
for (int i = 0; i < txOPs.length; i++) {
for (int j = 0; j < rootClasses.length; j++) {
// Check if object is of this root type
if (txOPs[i].getObject().getClass() == rootClasses[j]) {
// This ObjectProvider is for a valid root object
ops.add(txOPs[i]);
break;
}
}
}
} else if (cache != null && !cache.isEmpty()) {
// Detach all objects in the L1 cache
ops.addAll(cache.values());
}
// Make sure that all FetchPlan fields are loaded
Iterator<ObjectProvider> opsIter = ops.iterator();
while (opsIter.hasNext()) {
ObjectProvider op = opsIter.next();
Object pc = op.getObject();
if (pc != null && !getApiAdapter().isDetached(pc) && !getApiAdapter().isDeleted(pc)) {
// Load all fields (and sub-objects) in the FetchPlan
FetchPlanState state = new FetchPlanState();
try {
op.loadFieldsInFetchPlan(state);
} catch (NucleusObjectNotFoundException onfe) {
// This object doesnt exist in the datastore at this point.
// Either the user has some other process that has deleted it or they have
// defined datastore based cascade delete and it has been deleted that way
NucleusLogger.PERSISTENCE.warn(Localiser.msg("010013", StringUtils.toJVMIDString(pc), op.getInternalObjectId()));
opsIter.remove();
// TODO Move the object state to P_DELETED for consistency
}
}
}
detachAllOnTxnEndOPs = ops.toArray(new ObjectProvider[ops.size()]);
}
use of org.datanucleus.exceptions.NucleusObjectNotFoundException in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method persistObjectInternal.
/**
* Method to make an object persistent which should be called from internal calls only.
* All PM/EM calls should go via persistObject(Object obj).
* @param obj The object
* @param preInsertChanges Any changes to make before inserting
* @param ownerOP ObjectProvider of the owner when embedded
* @param ownerFieldNum Field number in the owner where this is embedded (or -1 if not embedded)
* @param objectType Type of object (see org.datanucleus.ObjectProvider, e.g ObjectProvider.PC)
* @return The persisted object
* @throws NucleusUserException if the object is managed by a different manager
*/
public <T> T persistObjectInternal(T obj, FieldValues preInsertChanges, ObjectProvider ownerOP, int ownerFieldNum, int objectType) {
if (obj == null) {
return null;
}
// TODO Support embeddedOwner/objectType, so we can add ObjectProvider for embedded objects here
ApiAdapter api = getApiAdapter();
// Id of the object that was persisted during this process (if any)
Object id = null;
try {
clr.setPrimary(obj.getClass().getClassLoader());
assertClassPersistable(obj.getClass());
ExecutionContext ec = api.getExecutionContext(obj);
if (ec != null && ec != this) {
// Object managed by a different manager
throw new NucleusUserException(Localiser.msg("010007", obj));
}
boolean cacheable = false;
// Persisted object is the passed in pc (unless being attached as a copy)
T persistedPc = obj;
if (api.isDetached(obj)) {
// Detached : attach it
assertDetachable(obj);
if (getBooleanProperty(PropertyNames.PROPERTY_COPY_ON_ATTACH)) {
// Attach a copy and return the copy
persistedPc = attachObjectCopy(ownerOP, obj, api.getIdForObject(obj) == null);
} else {
// Attach the object
attachObject(ownerOP, obj, api.getIdForObject(obj) == null);
persistedPc = obj;
}
} else if (api.isTransactional(obj) && !api.isPersistent(obj)) {
// TransientTransactional : persist it
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
if (op == null) {
throw new NucleusUserException(Localiser.msg("010007", getApiAdapter().getIdForObject(obj)));
}
op.makePersistentTransactionalTransient();
} else if (!api.isPersistent(obj)) {
// Transient : persist it
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
boolean merged = false;
ThreadContextInfo threadInfo = acquireThreadContextInfo();
try {
if (threadInfo.merging) {
AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(obj.getClass(), clr);
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
Object transientId = nucCtx.getIdentityManager().getApplicationId(obj, cmd);
if (transientId != null) {
// User has set id field(s) so find the datastore object (if exists)
T existingObj = (T) findObject(transientId, true, true, cmd.getFullClassName());
ObjectProvider existingOP = findObjectProvider(existingObj);
existingOP.attach(obj);
id = transientId;
merged = true;
persistedPc = existingObj;
}
}
cacheable = nucCtx.isClassCacheable(cmd);
}
} catch (NucleusObjectNotFoundException onfe) {
// Object with this id doesn't exist, so just persist the transient (below)
} finally {
releaseThreadContextInfo();
}
if (!merged) {
ObjectProvider<T> op = findObjectProvider(obj);
if (op == null) {
if ((objectType == ObjectProvider.EMBEDDED_COLLECTION_ELEMENT_PC || objectType == ObjectProvider.EMBEDDED_MAP_KEY_PC || objectType == ObjectProvider.EMBEDDED_MAP_VALUE_PC || objectType == ObjectProvider.EMBEDDED_PC) && ownerOP != null) {
// SCO object
op = nucCtx.getObjectProviderFactory().newForEmbedded(this, obj, false, ownerOP, ownerFieldNum);
op.setPcObjectType((short) objectType);
op.makePersistent();
id = op.getInternalObjectId();
} else {
// FCO object
op = nucCtx.getObjectProviderFactory().newForPersistentNew(this, obj, preInsertChanges);
op.makePersistent();
id = op.getInternalObjectId();
}
} else {
if (op.getReferencedPC() == null) {
// Persist it
op.makePersistent();
id = op.getInternalObjectId();
} else {
// Being attached, so use the attached object
persistedPc = op.getReferencedPC();
}
}
if (op != null) {
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
}
}
} else if (api.isPersistent(obj) && api.getIdForObject(obj) == null) {
// Should we be making a copy of the object here ?
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
op.makePersistent();
id = op.getInternalObjectId();
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
} else if (api.isDeleted(obj)) {
// Deleted : (re)-persist it (permitted in JPA, but not JDO - see ObjectProvider)
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
op.makePersistent();
id = op.getInternalObjectId();
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
} else {
if (api.isPersistent(obj) && api.isTransactional(obj) && api.isDirty(obj) && isDelayDatastoreOperationsEnabled()) {
// Object provisionally persistent (but not in datastore) so re-run reachability maybe
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("010015", StringUtils.toJVMIDString(obj)));
}
ObjectProvider op = findObjectProvider(obj);
op.makePersistent();
id = op.getInternalObjectId();
cacheable = nucCtx.isClassCacheable(op.getClassMetaData());
}
}
if (id != null && l2CacheTxIds != null && cacheable) {
l2CacheTxIds.add(id);
}
return persistedPc;
} finally {
clr.unsetPrimary();
}
}
use of org.datanucleus.exceptions.NucleusObjectNotFoundException in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method getClassDetailsForId.
/**
* Convenience method that takes an id, an optional class name for the object it represents, and whether
* to check for inheritance, and returns class details of the object being represented.
* Used by the findObject process.
* @param id The identity
* @param objectClassName Class name for the object (if known, otherwise is derived)
* @param checkInheritance Whether to check the inheritance level for this id
* @return The details for the class
*/
private ClassDetailsForId getClassDetailsForId(Object id, String objectClassName, boolean checkInheritance) {
// Object not found yet, so work out class name
String className = null;
String originalClassName = null;
boolean checkedClassName = false;
if (id instanceof SCOID) {
throw new NucleusUserException(Localiser.msg("010006"));
} else if (id instanceof DatastoreUniqueLongId) {
// Should have been found using "persistenceHandler.findObject()"
throw new NucleusObjectNotFoundException(Localiser.msg("010026"), id);
} else if (objectClassName != null) {
// Object class name specified so use that directly
originalClassName = objectClassName;
} else {
originalClassName = getStoreManager().manageClassForIdentity(id, clr);
}
if (originalClassName == null) {
// We dont know the object class so try to deduce it from what is known by the StoreManager
originalClassName = getClassNameForObjectId(id);
checkedClassName = true;
}
Object pc = null;
if (checkInheritance) {
// Validate the inheritance level
className = checkedClassName ? originalClassName : getClassNameForObjectId(id);
if (className == null) {
throw new NucleusObjectNotFoundException(Localiser.msg("010026"), id);
}
if (!checkedClassName) {
// Check if this id for any known subclasses is in the cache to save searching
if (IdentityUtils.isDatastoreIdentity(id) || IdentityUtils.isSingleFieldIdentity(id)) {
String[] subclasses = getMetaDataManager().getSubclassesForClass(className, true);
if (subclasses != null) {
for (int i = 0; i < subclasses.length; i++) {
Object oid = null;
if (IdentityUtils.isDatastoreIdentity(id)) {
oid = nucCtx.getIdentityManager().getDatastoreId(subclasses[i], IdentityUtils.getTargetKeyForDatastoreIdentity(id));
} else if (IdentityUtils.isSingleFieldIdentity(id)) {
oid = nucCtx.getIdentityManager().getSingleFieldId(id.getClass(), getClassLoaderResolver().classForName(subclasses[i]), IdentityUtils.getTargetKeyForSingleFieldIdentity(id));
}
pc = getObjectFromCache(oid);
if (pc != null) {
className = subclasses[i];
break;
}
}
}
}
}
if (pc == null && originalClassName != null && !originalClassName.equals(className)) {
// Inheritance check implies different inheritance level, so retry
if (IdentityUtils.isDatastoreIdentity(id)) {
// Create new OID using correct target class, and recheck cache
id = nucCtx.getIdentityManager().getDatastoreId(className, ((DatastoreId) id).getKeyAsObject());
pc = getObjectFromCache(id);
} else if (IdentityUtils.isSingleFieldIdentity(id)) {
// Create new SingleFieldIdentity using correct targetClass, and recheck cache
id = nucCtx.getIdentityManager().getSingleFieldId(id.getClass(), clr.classForName(className), IdentityUtils.getTargetKeyForSingleFieldIdentity(id));
pc = getObjectFromCache(id);
}
}
} else {
className = originalClassName;
}
return new ClassDetailsForId(id, className, pc);
}
use of org.datanucleus.exceptions.NucleusObjectNotFoundException in project datanucleus-rdbms by datanucleus.
the class FetchRequest method execute.
/* (non-Javadoc)
* @see org.datanucleus.store.rdbms.request.Request#execute(org.datanucleus.state.DNStateManager)
*/
public void execute(DNStateManager sm) {
if (fieldsToFetch != null && NucleusLogger.PERSISTENCE.isDebugEnabled()) {
// Debug information about what we are retrieving
NucleusLogger.PERSISTENCE.debug(Localiser.msg("052218", IdentityUtils.getPersistableIdentityForId(sm.getInternalObjectId()), fieldsToFetch, table));
}
if (((fetchingSurrogateVersion || versionFieldName != null) && numberOfFieldsToFetch == 0) && sm.isVersionLoaded()) {
// Fetching only the version and it is already loaded, so do nothing
} else if (statementLocked != null) {
ExecutionContext ec = sm.getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
// Override with pessimistic lock where specified
LockMode lockType = ec.getLockManager().getLockMode(sm.getInternalObjectId());
boolean locked = (lockType == LockMode.LOCK_PESSIMISTIC_READ || lockType == LockMode.LOCK_PESSIMISTIC_WRITE) ? true : ec.getSerializeReadForClass(sm.getClassMetaData().getFullClassName());
String statement = (locked ? statementLocked : statementUnlocked);
StatementClassMapping mappingDef = mappingDefinition;
/*if ((sm.isDeleting() || sm.isDetaching()) && mappingDefinition.hasChildMappingDefinitions())
{
// Don't fetch any children since the object is being deleted
mappingDef = mappingDefinition.cloneStatementMappingWithoutChildren();
}*/
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, statement);
AbstractClassMetaData cmd = sm.getClassMetaData();
try {
// Provide the primary key field(s) to the JDBC statement
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex datastoreIdx = mappingDef.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), sm.getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
sm.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(sm, ps, mappingDef));
}
JavaTypeMapping multitenancyMapping = table.getSurrogateMapping(SurrogateColumnType.MULTITENANCY, false);
if (multitenancyMapping != null) {
String[] tenantReadIds = storeMgr.getNucleusContext().getTenantReadIds(sm.getExecutionContext());
if (tenantReadIds != null && tenantReadIds.length > 0) {
// Using IN clause so nothing to do since hardcoded
} else {
// Set MultiTenancy tenant id in statement
StatementMappingIndex multitenancyIdx = mappingDef.getMappingForMemberPosition(SurrogateColumnType.MULTITENANCY.getFieldNumber());
String tenantId = ec.getTenantId();
for (int i = 0; i < multitenancyIdx.getNumberOfParameterOccurrences(); i++) {
multitenancyMapping.setObject(ec, ps, multitenancyIdx.getParameterPositionsForOccurrence(i), tenantId);
}
}
}
JavaTypeMapping softDeleteMapping = table.getSurrogateMapping(SurrogateColumnType.SOFTDELETE, false);
if (softDeleteMapping != null) {
// Set SoftDelete parameter in statement
StatementMappingIndex softDeleteIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.SOFTDELETE.getFieldNumber());
for (int i = 0; i < softDeleteIdx.getNumberOfParameterOccurrences(); i++) {
softDeleteMapping.setObject(ec, ps, softDeleteIdx.getParameterPositionsForOccurrence(i), Boolean.FALSE);
}
}
// Execute the statement
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
try {
// Check for failure to find the object
if (!rs.next()) {
String msg = Localiser.msg("050018", IdentityUtils.getPersistableIdentityForId(sm.getInternalObjectId()));
if (NucleusLogger.DATASTORE_RETRIEVE.isInfoEnabled()) {
NucleusLogger.DATASTORE_RETRIEVE.info(msg);
}
throw new NucleusObjectNotFoundException(msg);
}
// Copy the results into the object
ResultSetGetter rsGetter = new ResultSetGetter(ec, rs, mappingDef, sm.getClassMetaData());
rsGetter.setStateManager(sm);
// Make sure the version is set first
if (sm.getTransactionalVersion() == null) {
// Object has no version set so update it from this fetch
Object datastoreVersion = null;
if (fetchingSurrogateVersion) {
// Surrogate version column - get from the result set using the version mapping
StatementMappingIndex verIdx = mappingDef.getMappingForMemberPosition(SurrogateColumnType.VERSION.getFieldNumber());
datastoreVersion = table.getSurrogateMapping(SurrogateColumnType.VERSION, true).getObject(ec, rs, verIdx.getColumnPositions());
} else if (versionFieldName != null) {
// Version field - populate it in the object and access it from the field
int verAbsFieldNum = cmd.getAbsolutePositionOfMember(versionFieldName);
sm.replaceFields(new int[] { verAbsFieldNum }, rsGetter);
datastoreVersion = sm.provideField(verAbsFieldNum);
}
sm.setVersion(datastoreVersion);
}
// Fetch requested fields
sm.replaceFields(memberNumbersToFetch, rsGetter);
// Store requested fields
if (memberNumbersToStore != null) {
for (int i = 0; i < memberNumbersToStore.length; i++) {
StatementMappingIndex mapIdx = mappingDefinition.getMappingForMemberPosition(memberNumbersToStore[i]);
JavaTypeMapping m = mapIdx.getMapping();
if (m instanceof PersistableMapping) {
// FK, so create the identity of the related object
AbstractClassMetaData memberCmd = ((PersistableMapping) m).getClassMetaData();
Object memberId = null;
if (memberCmd.getIdentityType() == IdentityType.DATASTORE) {
memberId = MappingHelper.getDatastoreIdentityForResultSetRow(ec, m, rs, mapIdx.getColumnPositions(), memberCmd);
} else if (memberCmd.getIdentityType() == IdentityType.APPLICATION) {
memberId = MappingHelper.getApplicationIdentityForResultSetRow(ec, m, rs, mapIdx.getColumnPositions(), memberCmd);
} else {
break;
}
if (memberId == null) {
// Just set the member and don't bother saving the value
sm.replaceField(memberNumbersToStore[i], null);
} else {
// Store the "id" value in case the member is ever accessed
sm.storeFieldValue(memberNumbersToStore[i], memberId);
}
}
}
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException sqle) {
String msg = Localiser.msg("052219", IdentityUtils.getPersistableIdentityForId(sm.getInternalObjectId()), statement, sqle.getMessage());
NucleusLogger.DATASTORE_RETRIEVE.warn(msg);
List exceptions = new ArrayList();
exceptions.add(sqle);
while ((sqle = sqle.getNextException()) != null) {
exceptions.add(sqle);
}
throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
}
}
// Execute any mapping actions now that we have fetched the fields
if (mappingCallbacks != null) {
for (MappingCallbacks m : mappingCallbacks) {
m.postFetch(sm);
}
}
}
Aggregations