use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method createQuery.
/**
* @param queryLogicName
* @param queryParameters
* @return
*/
@POST
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@Path("/{logicName}/create")
@GZIP
@GenerateQuerySessionId(cookieBasePath = "/DataWave/Query/")
@EnrichQueryMetrics(methodType = MethodType.CREATE)
@Interceptors({ RequiredInterceptor.class, ResponseInterceptor.class })
@Timed(name = "dw.query.createQuery", absolute = true)
public GenericResponse<String> createQuery(@Required("logicName") @PathParam("logicName") String queryLogicName, MultivaluedMap<String, String> queryParameters, @Context HttpHeaders httpHeaders) {
CreateQuerySessionIDFilter.QUERY_ID.set(null);
QueryData qd = validateQuery(queryLogicName, queryParameters, httpHeaders);
GenericResponse<String> response = new GenericResponse<>();
Query q = null;
Connector connection = null;
AccumuloConnectionFactory.Priority priority;
Span createSpan = null;
RunningQuery rq = null;
try {
// Default hasResults to true. If a query logic is actually able to set this value,
// then their value will overwrite this one. Otherwise, we return true so that
// callers know they have to call next (even though next may not return results).
response.setHasResults(true);
AuditType auditType = qd.logic.getAuditType(null);
try {
MultivaluedMap<String, String> optionalQueryParameters = new MultivaluedMapImpl<>();
optionalQueryParameters.putAll(qp.getUnknownParameters(queryParameters));
q = persister.create(qd.userDn, qd.dnList, marking, queryLogicName, qp, optionalQueryParameters);
auditType = qd.logic.getAuditType(q);
} finally {
queryParameters.add(PrivateAuditConstants.AUDIT_TYPE, auditType.name());
if (!auditType.equals(AuditType.NONE)) {
// audit the query before its executed.
try {
try {
List<String> selectors = qd.logic.getSelectors(q);
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, q.getId().toString());
}
auditor.audit(queryParameters);
} catch (IllegalArgumentException e) {
log.error("Error validating audit parameters", 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;
}
}
}
priority = qd.logic.getConnectionPriority();
Map<String, String> trackingMap = connectionFactory.getTrackingMap(Thread.currentThread().getStackTrace());
addQueryToTrackingMap(trackingMap, q);
accumuloConnectionRequestBean.requestBegin(q.getId().toString());
try {
connection = connectionFactory.getConnection(qd.logic.getConnPoolName(), priority, trackingMap);
} finally {
accumuloConnectionRequestBean.requestEnd(q.getId().toString());
}
// If we're supposed to trace this query, then turn tracing on and set information about the query
// onto the span so that it is saved in the trace table.
TInfo traceInfo = null;
boolean shouldTraceQuery = shouldTraceQuery(qp.getQuery(), qd.userid, qp.isTrace());
if (shouldTraceQuery) {
Span span = Trace.on("query:" + q.getId());
log.debug("Tracing query " + q.getId() + " [" + qp.getQuery() + "] on trace ID " + Long.toHexString(span.traceId()));
for (Entry<String, List<String>> param : queryParameters.entrySet()) {
span.data(param.getKey(), param.getValue().get(0));
}
traceInfo = Tracer.traceInfo();
createSpan = Trace.start("query:create");
}
// hold on to a reference of the query logic so we cancel it if need be.
qlCache.add(q.getId().toString(), qd.userid, qd.logic, connection);
rq = new RunningQuery(metrics, null, priority, qd.logic, q, qp.getAuths(), qd.p, new RunningQueryTimingImpl(queryExpirationConf, qp.getPageTimeout()), this.executor, this.predictor, this.metricFactory);
rq.setActiveCall(true);
rq.setTraceInfo(traceInfo);
rq.getMetric().setProxyServers(qd.proxyServers);
rq.setConnection(connection);
// Put in the cache by id. Don't put the cache in by name because multiple users may use the same name
// and only the last one will be in the cache.
queryCache.put(q.getId().toString(), rq);
response.setResult(q.getId().toString());
rq.setActiveCall(false);
CreateQuerySessionIDFilter.QUERY_ID.set(q.getId().toString());
return response;
} catch (Throwable t) {
response.setHasResults(false);
if (rq != null) {
rq.getMetric().setError(t);
}
// close the logic on exception
try {
if (null != qd.logic) {
qd.logic.close();
}
} catch (Exception e) {
log.error("Exception occured while closing query logic; may be innocuous if scanners were running.", e);
}
if (null != connection) {
try {
connectionFactory.returnConnection(connection);
} catch (Exception e) {
log.error("Error returning connection on failed create", e);
}
}
try {
if (null != q)
persister.remove(q);
} catch (Exception e) {
response.addException(new QueryException(DatawaveErrorCode.DEPERSIST_ERROR, e).getBottomQueryException());
}
/*
* Allow web services to throw their own WebApplicationExceptions
*/
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 if (t instanceof InterruptedException) {
if (rq != null) {
rq.getMetric().setLifecycle(QueryMetric.Lifecycle.CANCELLED);
}
log.info("Query " + q.getId() + " canceled on request");
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_CANCELED, t);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
} else {
log.error(t.getMessage(), t);
QueryException qe = new QueryException(DatawaveErrorCode.RUNNING_QUERY_CACHE_ERROR, t);
response.addException(qe.getBottomQueryException());
int statusCode = qe.getBottomQueryException().getStatusCode();
throw new DatawaveWebApplicationException(qe, response, statusCode);
}
} finally {
if (createSpan != null) {
createSpan.stop();
// TODO: not sure this makes any sense anymore in Accumulo 1.8.1
// Stop the main query span since we're done working with it on this thread.
// We'll continue it later.
// createSpan.parent().stop();
}
if (null != q) {
// - Remove the logic from the cache
qlCache.poll(q.getId().toString());
}
}
}
use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class QueryExecutorBean method list.
/**
* Lists queries for the current user with the given name.
*
* @param name
* the name of the query to locate (@Required)
* @see datawave.webservice.query.runner.QueryExecutorBean#list(String) list(String) for the @Required definition
*
* @return datawave.webservice.result.QueryImplListResponse
* @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 404 if the query with {@code name} does not belong to caller, you will never see it
* @HTTP 404 queries not found using {@code name}
* @HTTP 400 if {@code name} parameter is not included
* @HTTP 500 internal server error
*/
@GET
@Path("/list")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@GZIP
@Interceptors({ RequiredInterceptor.class, ResponseInterceptor.class })
@Override
@Timed(name = "dw.query.listQueryByName", absolute = true)
public QueryImplListResponse list(@Required("name") @QueryParam("name") String name) {
QueryImplListResponse response = new QueryImplListResponse();
List<Query> results = new ArrayList<>();
try {
List<RunningQuery> query = getQueryByName(name);
if (null != query) {
for (RunningQuery rq : query) results.add(rq.getSettings());
}
response.setQuery(results);
return response;
} catch (DatawaveWebApplicationException e) {
throw e;
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.LIST_ERROR, e);
response.addException(qe.getBottomQueryException());
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 get.
/**
* Lists query info for the given id.
*
* @param id
* - the id of the query to locate (@Required)
* @see datawave.webservice.query.runner.QueryExecutorBean#get(String) get(String) for the @Required definition
*
* @return datawave.webservice.result.QueryImplListResponse
* @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 404 queries not found using {@code id}
* @HTTP 500 internal server error
*/
@GET
@Path("/{id}")
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@GZIP
@Interceptors({ RequiredInterceptor.class, ResponseInterceptor.class })
@Timed(name = "dw.query.listQueryByID", absolute = true)
public QueryImplListResponse get(@Required("id") @PathParam("id") String id) {
QueryImplListResponse response = new QueryImplListResponse();
List<Query> results = new ArrayList<>();
try {
RunningQuery query = getQueryById(id);
if (null != query) {
results.add(query.getSettings());
}
response.setQuery(results);
return response;
} catch (DatawaveWebApplicationException e) {
throw e;
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_GET_ERROR, e, MessageFormat.format("queryID: {0}", id));
log.error(qe, e);
response.addException(qe.getBottomQueryException());
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 remove.
/**
* remove (delete) the query
*
* @param id
*
* @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
* @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 404 queries not found using {@code id}
* @HTTP 500 internal server error
*/
@DELETE
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@Path("/{id}/remove")
@GZIP
@Interceptors({ ResponseInterceptor.class, RequiredInterceptor.class })
@Override
@Timed(name = "dw.query.remove", absolute = true)
public VoidResponse remove(@Required("id") @PathParam("id") String id) {
VoidResponse response = new VoidResponse();
try {
boolean connectionRequestCanceled = accumuloConnectionRequestBean.cancelConnectionRequest(id);
try {
RunningQuery query = getQueryById(id);
close(query);
persister.remove(query.getSettings());
} catch (Exception e) {
log.debug("Failed to remove " + id + ", checking if closed previously");
// if this is a query that is in the closed query cache, then we have already successfully closed this query so ignore
if (!closedQueryCache.exists(id)) {
log.debug("Failed to remove " + id + ", checking if connection request was canceled");
// if connection request was canceled, then the call was successful even if a RunningQuery was not found
if (!connectionRequestCanceled) {
log.error("Failed to remove " + id, e);
throw e;
}
}
}
response.addMessage(id + " removed.");
// no longer need to remember this query
closedQueryCache.remove(id);
return response;
} catch (DatawaveWebApplicationException e) {
throw e;
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.QUERY_REMOVAL_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);
}
}
use of datawave.webservice.query.exception.QueryException in project datawave by NationalSecurityAgency.
the class MapReduceBean method ooziesubmit.
/**
* Execute a Oozie workflow with the given workFlow name and runtime parameters
*
* @param queryParameters
* @return
*/
@POST
@Produces({ "application/xml", "text/xml", "application/json", "text/yaml", "text/x-yaml", "application/x-yaml", "application/x-protobuf", "application/x-protostuff" })
@javax.ws.rs.Path("/ooziesubmit")
@GZIP
public GenericResponse<String> ooziesubmit(MultivaluedMap<String, String> queryParameters) {
GenericResponse<String> response = new GenericResponse<>();
String workFlow = queryParameters.getFirst(OozieJobConstants.WORKFLOW_PARAM);
if (StringUtils.isBlank(workFlow)) {
throw new BadRequestException(new IllegalArgumentException(OozieJobConstants.WORKFLOW_PARAM + " parameter missing"), response);
}
String parameters = queryParameters.getFirst(OozieJobConstants.PARAMETERS);
// Find out who/what called this method
Principal p = ctx.getCallerPrincipal();
String sid = null;
String userDn = p.getName();
DatawavePrincipal datawavePrincipal = null;
if (p instanceof DatawavePrincipal) {
datawavePrincipal = (DatawavePrincipal) p;
sid = datawavePrincipal.getShortName();
} else {
QueryException qe = new QueryException(DatawaveErrorCode.UNEXPECTED_PRINCIPAL_ERROR, MessageFormat.format("Class: {0}", p.getClass().getName()));
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
}
OozieJobConfiguration job;
try {
MapReduceJobConfiguration mrConfig = this.mapReduceConfiguration.getConfiguration(workFlow);
if (mrConfig instanceof OozieJobConfiguration) {
job = (OozieJobConfiguration) mrConfig;
} else {
throw new IllegalArgumentException(workFlow + " not an Oozie job configuration");
}
} catch (IllegalArgumentException e) {
BadRequestQueryException qe = new BadRequestQueryException(DatawaveErrorCode.JOB_CONFIGURATION_ERROR, e);
response.addException(qe);
throw new BadRequestException(qe, response);
}
if (job instanceof NeedCallerDetails) {
((NeedCallerDetails) job).setUserSid(sid);
((NeedCallerDetails) job).setPrincipal(p);
}
// Ensure that the user has the required roles and has passed the required auths
if (null != job.getRequiredRoles() || null != job.getRequiredAuths()) {
try {
canRunJob(datawavePrincipal, queryParameters, job.getRequiredRoles(), job.getRequiredAuths());
} catch (UnauthorizedQueryException qe) {
// user does not have all of the required roles or did not pass the required auths
response.addException(qe);
throw new UnauthorizedException(qe, response);
}
}
String id = sid + "_" + UUID.randomUUID();
OozieClient oozieClient = null;
Properties oozieConf = null;
try {
oozieClient = new OozieClient((String) job.getJobConfigurationProperties().get(OozieJobConstants.OOZIE_CLIENT_PROP));
oozieConf = oozieClient.createConfiguration();
job.initializeOozieConfiguration(id, oozieConf, queryParameters);
job.validateWorkflowParameter(oozieConf, mapReduceConfiguration);
} catch (QueryException qe) {
log.error(qe.getMessage(), qe);
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
response.addException(new QueryException(e.getMessage(), e));
throw new DatawaveWebApplicationException(e, response);
} finally {
// audit query here
Auditor.AuditType auditType = job.getAuditType();
log.trace("Audit type is: " + auditType.name());
if (!auditType.equals(Auditor.AuditType.NONE)) {
try {
marking.validate(queryParameters);
PrivateAuditConstants.stripPrivateParameters(queryParameters);
queryParameters.putSingle(PrivateAuditConstants.USER_DN, userDn);
queryParameters.putSingle(PrivateAuditConstants.COLUMN_VISIBILITY, marking.toColumnVisibilityString());
queryParameters.putSingle(PrivateAuditConstants.AUDIT_TYPE, auditType.name());
List<String> selectors = job.getSelectors(queryParameters, oozieConf);
if (selectors != null && !selectors.isEmpty()) {
queryParameters.put(PrivateAuditConstants.SELECTORS, selectors);
}
// 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) {
log.error("Error validating audit parameters", 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);
response.addMessage("Error auditing query - " + e.getMessage());
throw new BadRequestException(e, response);
}
}
}
// Submit the Oozie workflow.
try {
String jobID = null;
try {
jobID = oozieClient.run(oozieConf);
} catch (Exception e) {
throw new QueryException(DatawaveErrorCode.OOZIE_JOB_START_ERROR, e);
}
try {
String jobResultstDir = oozieConf.getProperty(OozieJobConstants.OUT_DIR_PROP) + "/" + id;
response.setResult(id);
Path baseDir = new Path(this.mapReduceConfiguration.getMapReduceBaseDirectory());
// Create a directory path for this job
Path jobDir = new Path(baseDir, id);
mapReduceState.create(id, job.getHdfsUri(), job.getJobTracker(), jobDir.toString(), jobID, jobResultstDir, parameters, workFlow);
} catch (Exception e) {
QueryException qe = new QueryException(DatawaveErrorCode.MAPREDUCE_STATE_PERSISTENCE_ERROR, e);
response.addException(qe.getBottomQueryException());
try {
oozieClient.kill(jobID);
// if we successfully kill the job, throw the original exception
throw qe;
} catch (Exception e2) {
// throw the exception from killing the job
throw new QueryException(DatawaveErrorCode.MAPREDUCE_JOB_KILL_ERROR, e2);
}
}
} catch (QueryException qe) {
log.error(qe.getMessage(), qe);
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
QueryException qe = new QueryException(DatawaveErrorCode.UNKNOWN_SERVER_ERROR, e.getMessage());
response.addException(qe);
throw new DatawaveWebApplicationException(qe, response);
}
return response;
}
Aggregations