Skip to content
This repository was archived by the owner on Oct 6, 2023. It is now read-only.

Commit 5d7e560

Browse files
committed
Changed DataCite to be more verbose in its responses if there are issues
Signed-off-by: Neal Ensor <[email protected]>
1 parent cd65345 commit 5d7e560

File tree

2 files changed

+90
-68
lines changed

2 files changed

+90
-68
lines changed

src/main/java/gov/osti/doi/DataCite.java

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,10 @@ protected static String writeMetadata(DOECodeMetadata m) throws IOException, XML
334334
* Send a request to DataCite to register DOI metadata information.
335335
*
336336
* @param m the DOECodeMetadata object to register with DataCite
337-
* @return true if successful, false if not
337+
* @return "OK" on success, failure reason otherwise
338338
* @throws IOException on HTTP transmissions errors
339339
*/
340-
private static boolean registerMetadata(DOECodeMetadata m) throws IOException {
340+
private static String registerMetadata(DOECodeMetadata m) throws IOException {
341341
// set some reasonable default timeouts
342342
// create an HTTP client to request through
343343
CloseableHttpClient hc =
@@ -366,27 +366,28 @@ private static boolean registerMetadata(DOECodeMetadata m) throws IOException {
366366
HttpResponse response = hc.execute(request);
367367
int status_code = response.getStatusLine().getStatusCode();
368368
if ( HttpStatus.SC_CREATED==status_code )
369-
return true;
369+
return "OK";
370370
// otherwise, read the reason why
371371
log.warn("DOI request failed, response code=" + status_code);
372372
log.warn("Message: " + EntityUtils.toString(response.getEntity()));
373+
374+
return "DOI Metadata for " + m.getDoi() + " failed to register.";
373375
} catch ( XMLStreamException e ) {
374376
log.warn("XML metadata error: " + e.getMessage());
377+
return "Metadata format error: " + e.getMessage();
375378
} finally {
376379
hc.close();
377380
}
378-
// failed to post DOI information
379-
return false;
380381
}
381382

382383
/**
383384
* Send a request to DataCite to translate a DOI value to a URL to resolve.
384385
*
385386
* @param m the DOECodeMetadata Object to register with DataCite
386-
* @return true if successful, false if not
387-
* @throws IOException on HTTP transmission errors
387+
* @return "OK" if successful, failure response otherwise
388+
* @throws IOException on HTTP transmission errors, or failed to register DOI
388389
*/
389-
private static boolean registerDoi(DOECodeMetadata m) throws IOException {
390+
private static String registerDoi(DOECodeMetadata m) throws IOException {
390391
// set some reasonable default timeouts
391392
// create an HTTP client to request through
392393
CloseableHttpClient hc =
@@ -415,17 +416,17 @@ private static boolean registerDoi(DOECodeMetadata m) throws IOException {
415416
int status_code = response.getStatusLine().getStatusCode();
416417

417418
if ( HttpStatus.SC_CREATED==status_code )
418-
return true;
419+
return "OK";
419420

420421
// if we failed, explain why
421422
log.warn("DOI URL request failed, response code=" + status_code);
422423
log.warn("Message: " + EntityUtils.toString(response.getEntity()));
424+
425+
// do not send back too much information
426+
return "DOI URL for " + m.getDoi() + " failed to register.";
423427
} finally {
424428
hc.close();
425429
}
426-
427-
// failed to post DOI URL
428-
return false;
429430
}
430431

431432
/**
@@ -468,28 +469,48 @@ public static final boolean verifyDoiOwnership(DOECodeMetadata m) {
468469
* If DataCite information is not configured, or the register contains no
469470
* DOI value, this call is skipped.
470471
*
472+
* Returns:
473+
* "OK" on successful operation, or failure reason if not.
474+
*
471475
* @param m the DOECodeMetadata object to register
472-
* @return true if successful, false if not
476+
* @return "OK" if successful, or failure excuse if not
473477
* @throws IOException on HTTP transmission errors
474478
*/
475-
public static boolean register(DOECodeMetadata m) throws IOException {
479+
public static String register(DOECodeMetadata m) throws IOException {
476480
// if not configured, ignore this call
477481
if ("".equals(DATACITE_LOGIN))
478-
return true;
482+
return "OK"; // this is still okay
479483
// if no DOI is requested, skip this
480484
if (null==m.getDoi())
481-
return true;
485+
return "OK"; // nothing to do
482486

483487
// ensure the DOI to be registered is recognized and valid for this record
484488
// do we know this prefix?
485489
if (!m.getDoi().startsWith(DATACITE_PREFIX))
486-
return true;
490+
return "OK"; // somebody else's DOI
487491

488492
// check to make sure we can proceed ( SHOULD NOT BE REGISTERED ELSEWHERE )
489493
if (!verifyDoiOwnership(m))
490-
return false;
494+
return "DOI " + m.getDoi() + " is not exclusive to code ID " + m.getCodeId();
491495

492496
// try the registration, returning success or failure
493-
return (registerMetadata(m) && registerDoi(m));
497+
try {
498+
// attempt to register METADATA
499+
String metadataResponse = registerMetadata(m);
500+
if (!"OK".equals(metadataResponse))
501+
return metadataResponse;
502+
503+
// attempt to register DOI
504+
String doiResponse = registerDoi(m);
505+
if (!"OK".equals(doiResponse))
506+
return doiResponse;
507+
} catch ( IOException e ) {
508+
// some general transmission error occurred
509+
log.warn("DOI registration failed: " + e);
510+
return "DOI transmission failure.";
511+
}
512+
513+
// if we made it here, all is OK
514+
return "OK";
494515
}
495516
}

src/main/java/gov/osti/services/Metadata.java

Lines changed: 50 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -698,26 +698,23 @@ public Response asYAML(String object) {
698698
/**
699699
* Send this Metadata to the ARCHIVER external support process.
700700
*
701-
* Archiver needs the CODE ID, a PROJECT NAME (taken from the acronym if
702-
* present, or the title), an optional PROJECT DESCRIPTION, and either a
703-
* REPOSITORY LINK value or FILE NAME if uploaded file exists.
704-
705-
*
701+
* Needs a CODE ID and one of either an ARCHIVE FILE or REPOSITORY LINK.
702+
*
706703
* If nothing supplied to archive, do nothing.
707704
*
708-
* @param md the DOECodeMetadata to archive
705+
* @param codeId the CODE ID for this METADATA
706+
* @param repositoryLink (optional) the REPOSITORY LINK value, or null if none
707+
* @param archiveFile (optional) the File recently uploaded to ARCHIVE, or null if none
709708
* @throws IOException on IO transmission errors
710709
*/
711-
private static void sendToArchiver(DOECodeMetadata md) throws IOException {
710+
private static void sendToArchiver(Long codeId, String repositoryLink, File archiveFile) throws IOException {
712711
if ( "".equals(ARCHIVER_URL) )
713712
return;
714713

715-
// if NOTHING to archive (no FILE or REPOSITORY LINK) just leave
716-
if (StringUtils.isBlank(md.getFileName()) &&
717-
StringUtils.isBlank(md.getRepositoryLink()))
714+
// Nothing sent?
715+
if (StringUtils.isBlank(repositoryLink) && null==archiveFile)
718716
return;
719-
720-
717+
721718
// set up a connection
722719
CloseableHttpClient hc =
723720
HttpClientBuilder
@@ -734,11 +731,11 @@ private static void sendToArchiver(DOECodeMetadata md) throws IOException {
734731
HttpPost post = new HttpPost(ARCHIVER_URL);
735732
// attributes to send
736733
ObjectNode request = mapper.createObjectNode();
737-
request.put("code_id", md.getCodeId());
738-
request.put("repository_link", md.getRepositoryLink());
734+
request.put("code_id", codeId);
735+
request.put("repository_link", repositoryLink);
739736

740737
// determine if there's a file to send or not
741-
if (null==md.getFileName()) {
738+
if (null==archiveFile) {
742739
post.setHeader("Content-Type", "application/json");
743740
post.setHeader("Accept", "application/json");
744741

@@ -747,7 +744,7 @@ private static void sendToArchiver(DOECodeMetadata md) throws IOException {
747744
post.setEntity(MultipartEntityBuilder
748745
.create()
749746
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
750-
.addPart("file", new FileBody(new File(md.getFileName()), ContentType.DEFAULT_BINARY))
747+
.addPart("file", new FileBody(archiveFile, ContentType.DEFAULT_BINARY))
751748
.addPart("project", new StringBody(request.toString(), ContentType.APPLICATION_JSON))
752749
.build());
753750
}
@@ -892,9 +889,9 @@ private Response doSave(String json, InputStream file, FormDataContentDispositio
892889
}
893890

894891
/**
895-
* Handle PUBLISH workflow logic.
892+
* Handle SUBMIT workflow logic.
896893
*
897-
* @param json JSON String containing the METADATA object to PUBLISH
894+
* @param json JSON String containing the METADATA object to SUBMIT
898895
* @param file (optional) a FILE associated with this METADATA
899896
* @param fileInfo (optional) the FILE disposition information, if any
900897
* @return an appropriate Response object to the caller
@@ -921,7 +918,7 @@ private Response doSubmit(String json, InputStream file, FormDataContentDisposit
921918
if ( !errors.isEmpty() ) {
922919
// generate a JSONAPI errors object
923920
return ErrorResponse
924-
.status(Response.Status.BAD_REQUEST, errors)
921+
.badRequest(errors)
925922
.build();
926923
}
927924

@@ -936,62 +933,64 @@ private Response doSubmit(String json, InputStream file, FormDataContentDisposit
936933
} catch ( IOException e ) {
937934
log.error ("File Upload Failed: " + e.getMessage());
938935
return ErrorResponse
939-
.status(Response.Status.INTERNAL_SERVER_ERROR, "File upload failed.")
936+
.internalServerError("File upload failed.")
940937
.build();
941938
}
942939
}
943940
// send this file upload along to archiver if configured
944941
try {
945-
sendToArchiver(md);
942+
// if a FILE was sent, create a File Object from it
943+
File archiveFile = (null==file) ? null : new File(md.getFileName());
944+
sendToArchiver(md.getCodeId(), md.getRepositoryLink(), archiveFile);
946945
} catch ( IOException e ) {
947946
log.error("Archiver call failure: " + e.getMessage());
948947
return ErrorResponse
949-
.status(Response.Status.INTERNAL_SERVER_ERROR, "Unable to archive project.")
948+
.internalServerError("Unable to archive project.")
950949
.build();
951950
}
952-
953951
// send to DataCite if needed
954952
if ( null!=md.getDoi() ) {
955-
if ( !DataCite.register(md) ) {
956-
log.warn("DataCite registration failed for " + md.getDoi());
957-
throw new IOException ("DOI registration failed.");
958-
}
953+
String doiResponse = DataCite.register(md);
954+
if (!"OK".equals(doiResponse))
955+
return ErrorResponse
956+
.internalServerError(doiResponse)
957+
.build();
959958
}
960959
// commit it
961960
em.getTransaction().commit();
962961

963962
// we are done here
964963
return Response
965-
.status(Response.Status.OK)
964+
.ok()
966965
.entity(mapper.createObjectNode().putPOJO("metadata", md.toJson()).toString())
967966
.build();
968967
} catch ( NotFoundException e ) {
969968
return ErrorResponse
970-
.status(Response.Status.NOT_FOUND, e.getMessage())
969+
.notFound(e.getMessage())
971970
.build();
972971
} catch ( IllegalAccessException e ) {
973972
log.warn("Persistence Error: Unable to update record, invalid owner: " + user.getEmail());
974973
log.warn("Message: " + e.getMessage());
975974
return ErrorResponse
976-
.status(Response.Status.FORBIDDEN, "Logged in User is not allowed to modify this record.")
975+
.forbidden("Logged in User is not allowed to modify this record.")
977976
.build();
978977
} catch ( IOException | InvocationTargetException e ) {
979978
if ( em.getTransaction().isActive())
980979
em.getTransaction().rollback();
981980

982981
log.warn("Persistence Error Submitting: " + e.getMessage());
983982
return ErrorResponse
984-
.status(Response.Status.INTERNAL_SERVER_ERROR, "Persistence error submitting record.")
983+
.internalServerError("Persistence error submitting record.")
985984
.build();
986985
} finally {
987986
em.close();
988987
}
989988
}
990989

991990
/**
992-
* Perform SUBMIT workflow operation, optionally with associated file uploads.
991+
* Perform ANNOUNCE workflow operation, optionally with associated file uploads.
993992
*
994-
* @param json String containing JSON of the Metadata to SUBMIT
993+
* @param json String containing JSON of the Metadata to ANNOUNCE
995994
* @param file the FILE (if any) to attach to this metadata
996995
* @param fileInfo file disposition information if FILE present
997996
* @return a Response containing the JSON of the submitted record if successful, or
@@ -1035,7 +1034,7 @@ private Response doAnnounce(String json, InputStream file, FormDataContentDispos
10351034
} catch ( IOException e ) {
10361035
log.error ("File Upload Failed: " + e.getMessage());
10371036
return ErrorResponse
1038-
.status(Response.Status.INTERNAL_SERVER_ERROR, "File upload failed.")
1037+
.internalServerError("File upload failed.")
10391038
.build();
10401039
}
10411040
}
@@ -1044,7 +1043,7 @@ private Response doAnnounce(String json, InputStream file, FormDataContentDispos
10441043
List<String> errors = validateAnnounce(md);
10451044
if ( !errors.isEmpty() ) {
10461045
return ErrorResponse
1047-
.status(Response.Status.BAD_REQUEST, errors)
1046+
.badRequest(errors)
10481047
.build();
10491048
}
10501049
// send this to OSTI
@@ -1083,48 +1082,50 @@ private Response doAnnounce(String json, InputStream file, FormDataContentDispos
10831082
hc.close();
10841083
}
10851084
}
1086-
// send any updates to DataCite as well
1087-
if (StringUtils.isNotEmpty(md.getDoi())) {
1088-
if ( !DataCite.register(md) ) {
1089-
log.warn("DataCite DOI registration failed for " + md.getDoi() + " ID=" + md.getCodeId());
1090-
throw new IOException ("DOI registration failed.");
1091-
}
1092-
}
10931085
// send this file upload along to archiver if configured
10941086
try {
1095-
sendToArchiver(md);
1087+
File archiveFile = (null==file) ? null : new File(md.getFileName());
1088+
sendToArchiver(md.getCodeId(), md.getRepositoryLink(), archiveFile);
10961089
} catch ( IOException e ) {
10971090
log.error("Archiver call failure: " + e.getMessage());
10981091
return ErrorResponse
1099-
.status(Response.Status.INTERNAL_SERVER_ERROR, "Unable to archive project.")
1092+
.internalServerError("Unable to archive project.")
11001093
.build();
11011094
}
1102-
1095+
// send any updates to DataCite as well
1096+
if (StringUtils.isNotEmpty(md.getDoi())) {
1097+
String doiResponse = DataCite.register(md);
1098+
1099+
if (!"OK".equals(doiResponse))
1100+
return ErrorResponse
1101+
.internalServerError(doiResponse)
1102+
.build();
1103+
}
11031104
// if we make it this far, go ahead and commit the transaction
11041105
em.getTransaction().commit();
11051106

11061107
// and we're happy
11071108
return Response
1108-
.status(Response.Status.OK)
1109+
.ok()
11091110
.entity(mapper.createObjectNode().putPOJO("metadata", md.toJson()).toString())
11101111
.build();
11111112
} catch ( NotFoundException e ) {
11121113
return ErrorResponse
1113-
.status(Response.Status.NOT_FOUND, e.getMessage())
1114+
.notFound(e.getMessage())
11141115
.build();
11151116
} catch ( IllegalAccessException e ) {
11161117
log.warn("Persistence Error: Invalid owner update attempt: " + user.getEmail());
11171118
log.warn("Message: " + e.getMessage());
11181119
return ErrorResponse
1119-
.status(Response.Status.FORBIDDEN, "Invalid Access: Unable to edit indicated record.")
1120+
.forbidden("Invalid Access: Unable to edit indicated record.")
11201121
.build();
11211122
} catch ( IOException | InvocationTargetException e ) {
11221123
if ( em.getTransaction().isActive())
11231124
em.getTransaction().rollback();
11241125

11251126
log.warn("Persistence Error: " + e.getMessage());
11261127
return ErrorResponse
1127-
.status(Response.Status.INTERNAL_SERVER_ERROR, "IO Error announcing record.")
1128+
.internalServerError("IO Error announcing record.")
11281129
.build();
11291130
} finally {
11301131
em.close();

0 commit comments

Comments
 (0)