use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method duplicateQuery.
/**
* Duplicates a query and allows modification of optional properties
*
* @param id
* - the ID of the query to copy (required)
* @param newQueryName
* - name of the new query (@Required)
* @param newQueryLogicName
* - defaults to old logic, name of class that this query should be run with (optional)
* @param newQuery
* - defaults to old query, string used in lookup (optional, auditing required if changed)
* @param newColumnVisibility
* - defaults to old column visibility, for query AND justification (optional, auditing required if changed)
* @param newBeginDate
* - defaults to old begin date, begin range for the query (optional, auditing required if changed)
* @param newEndDate
* - defaults to old end date, end range for the query (optional, auditing required if changed)
* @param newQueryAuthorizations
* - defaults to old authorizations, use in the query (optional, auditing required if changed)
* @param newExpirationDate
* - defaults to old expiration, meaningless if transient (optional)
* @param newPagesize
* - defaults to old pagesize, number of results to return on each call to next() (optional)
* @param newPageTimeout
* - specify timeout (in minutes) for each call to next(), defaults to -1 indicating disabled (optional)
* @param newMaxResultsOverride
* - specify max results (optional)
* @param newPersistenceMode
* - defaults to PERSISTENT, indicates whether or not the query is persistent (optional)
* @param newParameters
* - defaults to old, optional parameters to the query, a semi-colon separated list name=value pairs (optional, auditing required if changed)
* @param trace
* - optional (defaults to {@code false}) indication of whether or not the query should be traced using the distributed tracing mechanism
* @see datawave.webservice.query.runner.QueryExecutorBean#duplicateQuery(String, String, String, String, String, Date, Date, String, Date, Integer,
* Integer, Long, QueryPersistence, String, boolean)
*
* @return {@code datawave.webservice.result.GenericResponse<String>}
* @RequestHeader X-ProxiedEntitiesChain use when proxying request for user, by specifying a chain of DNs of the identities to proxy
* @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
* @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
*
* @HTTP 200 success
* @HTTP 400 if invalid params or missing queryName param
* @HTTP 404 if query not found
* @HTTP 500 internal server error
*/
@POST
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@Path("/{id}/duplicate")
@GZIP
@Interceptors({ ResponseInterceptor.class, RequiredInterceptor.class })
@Override
@Timed(name = "dw.query.duplicateQuery", absolute = true)
public GenericResponse<String> duplicateQuery(@PathParam("id") String id, @Required("queryName") @FormParam("queryName") String newQueryName, @FormParam("logicName") String newQueryLogicName, @FormParam("query") String newQuery, @FormParam("columnVisibility") String newColumnVisibility, @FormParam("begin") @DateFormat(defaultTime = "000000", defaultMillisec = "000") Date newBeginDate, @FormParam("end") @DateFormat(defaultTime = "235959", defaultMillisec = "999") Date newEndDate, @FormParam("auths") String newQueryAuthorizations, @FormParam("expiration") @DateFormat(defaultTime = "235959", defaultMillisec = "999") Date newExpirationDate, @FormParam("pagesize") Integer newPagesize, @FormParam("pageTimeout") Integer newPageTimeout, @FormParam("maxResultsOverride") Long newMaxResultsOverride, @FormParam("persistence") QueryPersistence newPersistenceMode, @FormParam("params") String newParameters, @FormParam("trace") @DefaultValue("false") boolean trace) {
GenericResponse<String> response = new GenericResponse<>();
try {
if (null == newQueryName || newQueryName.length() < 1) {
throw new BadRequestQueryException(DatawaveErrorCode.QUERY_NAME_REQUIRED);
}
RunningQuery templateQuery = getQueryById(id);
Query q = templateQuery.getSettings().duplicate(newQueryName);
// default value
QueryPersistence persistence = QueryPersistence.PERSISTENT;
// TODO: figure out a way to set this to the same as the existing query
if (null != newPersistenceMode) {
persistence = newPersistenceMode;
}
// maybe set variables instead of stuffing in query
if (newQueryLogicName != null) {
q.setQueryLogicName(queryLogicFactory.getQueryLogic(newQueryLogicName, ctx.getCallerPrincipal()).getLogicName());
}
if (newQuery != null) {
q.setQuery(newQuery);
}
if (newBeginDate != null) {
q.setBeginDate(newBeginDate);
}
if (newEndDate != null) {
q.setEndDate(newEndDate);
}
if (newQueryAuthorizations != null) {
q.setQueryAuthorizations(newQueryAuthorizations);
}
if (newExpirationDate != null) {
q.setExpirationDate(newExpirationDate);
}
if (newPagesize != null) {
q.setPagesize(newPagesize);
}
if (newMaxResultsOverride != null) {
q.setMaxResultsOverride(newMaxResultsOverride);
}
if (newPageTimeout != null) {
q.setPageTimeout(newPageTimeout);
}
Set<Parameter> params = new HashSet<>();
if (newParameters != null) {
String[] param = newParameters.split(QueryImpl.PARAMETER_SEPARATOR);
for (String yyy : param) {
String[] parts = yyy.split(QueryImpl.PARAMETER_NAME_VALUE_SEPARATOR);
if (parts.length == 2) {
params.add(new Parameter(parts[0], parts[1]));
}
}
}
MultivaluedMap<String, String> newSettings = new MultivaluedMapImpl<>();
newSettings.putAll(q.toMap());
newSettings.putSingle(QueryParameters.QUERY_PERSISTENCE, persistence.name());
return createQuery(q.getQueryLogicName(), newSettings);
} catch (DatawaveWebApplicationException e) {
throw e;
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_DUPLICATION_ERROR, e);
log.error(qe, e);
response.addException(qe.getBottomQueryException());
if (e.getClass() == IllegalArgumentException.class) {
throw new BadRequestException(qe, response);
}
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
}
}
use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method plan.
/**
* Pulls back the current plan for a query.
*
* @param id
* - (@Required)
*
* @return GenericResponse containing plan
* @RequestHeader X-ProxiedEntitiesChain use when proxying request for user, by specifying a chain of DNs of the identities to proxy
* @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
* @RequestHeader query-session-id session id value used for load balancing purposes. query-session-id can be placed in the request in a Cookie header or as
* a query parameter
* @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
*
* @HTTP 200 success
* @HTTP 204 success and no results
* @HTTP 404 if id not found
* @HTTP 412 if the query is no longer alive, client should call {@link #reset(String)} and try again
* @HTTP 500 internal server error
*/
@GET
@Path("/{id}/plan")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@GZIP
@Interceptors({ ResponseInterceptor.class, RequiredInterceptor.class })
@Override
@Timed(name = "dw.query.plan", absolute = true)
public GenericResponse<String> plan(@Required("id") @PathParam("id") String id) {
// in case we don't make it to creating the response from the QueryLogic
GenericResponse<String> response = new GenericResponse<>();
Principal p = ctx.getCallerPrincipal();
String userid = p.getName();
if (p instanceof DatawavePrincipal) {
DatawavePrincipal dp = (DatawavePrincipal) p;
userid = dp.getShortName();
}
try {
// Not calling getQueryById() here. We don't want to pull the persisted definition.
RunningQuery query = queryCache.get(id);
// an error.
if (null == query || null == query.getConnection()) {
// status code.
if (null == query) {
List<Query> queries = persister.findById(id);
if (queries == null || queries.size() != 1) {
throw new NotFoundQueryException(DatawaveErrorCode.NO_QUERY_OBJECT_MATCH, MessageFormat.format("{0}", id));
}
}
throw new PreConditionFailedQueryException(DatawaveErrorCode.QUERY_TIMEOUT_OR_SERVER_ERROR, MessageFormat.format("id = {0}", id));
} else {
// Validate the query belongs to the caller
if (!query.getSettings().getOwner().equals(userid)) {
throw new UnauthorizedQueryException(DatawaveErrorCode.QUERY_OWNER_MISMATCH, MessageFormat.format("{0} != {1}", userid, query.getSettings().getOwner()));
}
// pull the plan out of the query metric
String plan = query.getMetric().getPlan();
if (plan != null) {
response.setResult(plan);
response.setHasResults(true);
}
}
} catch (Exception e) {
log.error("Failed to get query plan", e);
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_PLAN_ERROR, e, MessageFormat.format("query id: {0}", id));
log.error(qe, e);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
}
return response;
}
use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method reset.
/**
* Resets the query named by {@code id}. If the query is not alive, meaning that the current session has expired (due to either timeout, or server failure),
* then this will reload the query and start it over. If the query is alive, it closes it and starts the query over.
*
* @param id
* the ID of the query to reload/reset
* @return an empty response
*
* @return datawave.webservice.result.VoidResponse
* @RequestHeader X-ProxiedEntitiesChain use when proxying request for user, by specifying a chain of DNs of the identities to proxy
* @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
* @ResponseHeader query-session-id this header and value will be in the Set-Cookie header, subsequent calls for this session will need to supply the
* query-session-id header in the request in a Cookie header or as a query parameter
* @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
*
* @HTTP 200 success
* @HTTP 400 invalid or missing parameter
* @HTTP 500 internal server error
*/
@PUT
@POST
@Path("/{id}/reset")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@GZIP
@GenerateQuerySessionId(cookieBasePath = "/DataWave/Query/")
@Interceptors({ ResponseInterceptor.class, RequiredInterceptor.class })
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Override
@Timed(name = "dw.query.reset", absolute = true)
public VoidResponse reset(@Required("id") @PathParam("id") String id) {
CreateQuerySessionIDFilter.QUERY_ID.set(null);
VoidResponse response = new VoidResponse();
AccumuloConnectionFactory.Priority priority;
Connector connection = null;
RunningQuery query = null;
Span span = null;
try {
ctx.getUserTransaction().begin();
query = getQueryById(id);
// If we're tracing this query, then continue the trace for the reset call.
TInfo traceInfo = query.getTraceInfo();
if (traceInfo != null) {
span = Trace.trace(traceInfo, "query:reset");
}
// The lock should be released at the end of the method call.
if (!queryCache.lock(id))
throw new QueryException(DatawaveErrorCode.QUERY_LOCKED_ERROR);
// restarting the query, so we should re-audit ().
if (query.getConnection() != null) {
query.closeConnection(connectionFactory);
} else {
AuditType auditType = query.getLogic().getAuditType(query.getSettings());
MultivaluedMap<String, String> queryParameters = new MultivaluedMapImpl<>();
queryParameters.putAll(query.getSettings().toMap());
queryParameters.putSingle(PrivateAuditConstants.AUDIT_TYPE, auditType.name());
queryParameters.putSingle(PrivateAuditConstants.LOGIC_CLASS, query.getLogic().getLogicName());
queryParameters.putSingle(PrivateAuditConstants.USER_DN, query.getSettings().getUserDN());
queryParameters.putSingle(PrivateAuditConstants.COLUMN_VISIBILITY, query.getSettings().getColumnVisibility());
if (!auditType.equals(AuditType.NONE)) {
try {
try {
List<String> selectors = query.getLogic().getSelectors(query.getSettings());
if (selectors != null && !selectors.isEmpty()) {
queryParameters.put(PrivateAuditConstants.SELECTORS, selectors);
}
} catch (Exception e) {
log.error("Error accessing query selector", e);
}
// if the user didn't set an audit id, use the query id
if (!queryParameters.containsKey(AuditParameters.AUDIT_ID)) {
queryParameters.putSingle(AuditParameters.AUDIT_ID, id);
}
auditor.audit(queryParameters);
} catch (IllegalArgumentException e) {
BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.MISSING_REQUIRED_PARAMETER, e);
response.addException(qe);
throw new BadRequestException(qe, response);
} catch (Exception e) {
log.error("Error auditing query", e);
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_AUDITING_ERROR, e);
response.addException(qe);
throw qe;
}
}
}
// Allocate the connection for this query so we are ready to go when
// they call next.
priority = query.getConnectionPriority();
Map<String, String> trackingMap = connectionFactory.getTrackingMap(Thread.currentThread().getStackTrace());
addQueryToTrackingMap(trackingMap, query.getSettings());
accumuloConnectionRequestBean.requestBegin(id);
try {
connection = connectionFactory.getConnection(query.getLogic().getConnPoolName(), priority, trackingMap);
} finally {
accumuloConnectionRequestBean.requestEnd(id);
}
query.setConnection(connection);
response.addMessage(id + " reset.");
CreateQuerySessionIDFilter.QUERY_ID.set(id);
return response;
} catch (InterruptedException e) {
if (query != null) {
query.getMetric().setLifecycle(QueryMetric.Lifecycle.CANCELLED);
}
log.info("Query " + id + " canceled on request");
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_CANCELED, e);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
} catch (Exception e) {
log.error("Exception caught on resetting query", e);
try {
if (null != connection) {
/*
* if the query exists, we need to make sure the connection isn't set on it because the "proper" work flow is to close and/or cancel the
* query after a failure. we don't want to purge it from the query cache, so setting the connector to null avoids having the connector
* returned multiple times to the connector pool.
*/
if (query != null) {
query.setConnection(null);
}
connectionFactory.returnConnection(connection);
}
} catch (Exception e2) {
log.error("Error returning connection on failed reset", e2);
}
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_RESET_ERROR, e);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
} finally {
queryCache.unlock(id);
try {
if (ctx.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
// no reason to commit if transaction not started, ie Query not found exception
ctx.getUserTransaction().commit();
}
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_TRANSACTION_ERROR, e);
response.addException(qe.getBottomQueryException());
throw new DatawaveWebApplicationException(qe, response);
} finally {
// Stop timing on this trace, if any
if (span != null) {
span.stop();
}
}
}
}
use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method predictQuery.
/**
* @param queryLogicName
* @param queryParameters
* @return query predictions
*/
@POST
@Path("/{logicName}/predict")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@Interceptors({ RequiredInterceptor.class, ResponseInterceptor.class })
@Timed(name = "dw.query.predictQuery", absolute = true)
public GenericResponse<String> predictQuery(@Required("logicName") @PathParam("logicName") String queryLogicName, MultivaluedMap<String, String> queryParameters) {
CreateQuerySessionIDFilter.QUERY_ID.set(null);
QueryData qd = validateQuery(queryLogicName, queryParameters, null);
GenericResponse<String> response = new GenericResponse<>();
if (predictor != null) {
try {
qp.setPersistenceMode(QueryPersistence.TRANSIENT);
MultivaluedMap<String, String> optionalQueryParameters = new MultivaluedMapImpl<>();
optionalQueryParameters.putAll(qp.getUnknownParameters(queryParameters));
Query q = persister.create(qd.userDn, qd.dnList, marking, queryLogicName, qp, optionalQueryParameters);
BaseQueryMetric metric = metricFactory.createMetric();
metric.populate(q);
metric.setQueryType(RunningQuery.class.getSimpleName());
Set<Prediction> predictions = predictor.predict(metric);
if (predictions != null && !predictions.isEmpty()) {
String predictionString = predictions.toString();
// now we have a predictions, lets broadcast
log.info("Model predictions: " + predictionString);
response.setHasResults(true);
response.setResult(predictionString);
} else {
response.setHasResults(false);
}
} catch (Throwable t) {
response.setHasResults(false);
if (t instanceof Error && !(t instanceof TokenMgrError)) {
log.error(t.getMessage(), t);
throw (Error) t;
} else if (t instanceof WebApplicationException) {
log.error(t.getMessage(), t);
throw ((WebApplicationException) t);
} else {
log.error(t.getMessage(), t);
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_PREDICTIONS_ERROR, t);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
}
}
} else {
response.setHasResults(false);
}
return response;
}
use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class ExtendedQueryExecutorBeanTest method testNext_QueryExceptionDueToCacheLock.
@Test
public void testNext_QueryExceptionDueToCacheLock() throws Exception {
// Set local test input
String userName = "userName";
String userSid = "userSid";
UUID queryId = UUID.randomUUID();
// Set expectations
expect(this.context.getCallerPrincipal()).andReturn(this.principal).anyTimes();
expect(this.principal.getName()).andReturn(userName);
expect(this.principal.getShortName()).andReturn(userSid);
expect(this.principal.getProxyServers()).andReturn(new ArrayList<>(0));
expect(this.context.getUserTransaction()).andReturn(this.transaction).anyTimes();
this.transaction.begin();
expect(this.cache.get(queryId.toString())).andReturn(this.runningQuery);
expect(this.cache.lock(queryId.toString())).andReturn(false);
expect(this.responseObjectFactory.getEventQueryResponse()).andReturn(new DefaultEventQueryResponse());
this.runningQuery.setActiveCall(false);
expect(this.runningQuery.getLogic()).andReturn((QueryLogic) this.queryLogic1);
expect(this.queryLogic1.getCollectQueryMetrics()).andReturn(true);
expect(this.runningQuery.getMetric()).andReturn(this.queryMetric).times(2);
expectLastCall();
this.queryMetric.setError(isA(Throwable.class));
this.metrics.updateMetric(this.queryMetric);
cache.unlock(queryId.toString());
this.transaction.setRollbackOnly();
expect(this.transaction.getStatus()).andThrow(ILLEGAL_STATE_EXCEPTION);
// Run the test
PowerMock.replayAll();
QueryExecutorBean subject = new QueryExecutorBean();
setInternalState(subject, EJBContext.class, context);
setInternalState(subject, QueryCache.class, cache);
setInternalState(subject, ClosedQueryCache.class, closedCache);
setInternalState(subject, QueryMetricsBean.class, metrics);
setInternalState(subject, ResponseObjectFactory.class, responseObjectFactory);
setInternalState(subject, QueryMetricFactory.class, new QueryMetricFactoryImpl());
Exception result1 = null;
try {
subject.next(queryId.toString());
} catch (DatawaveWebApplicationException e) {
result1 = e;
}
PowerMock.verifyAll();
// Verify results
assertNotNull("Expected a DatawaveWebApplicationException to be thrown", result1);
assertEquals("Expected DatawaveWebApplicationException to have been caused by a locked cache entry", "500-9", ((QueryException) result1.getCause().getCause()).getErrorCode());
}
Aggregations