Commit ad40382f5e8b66e67e883a2998330aa5a9b96871

Authored by Paulo Graça

Merge branch 'master' of gitlab.fccn.pt:dev-ptcris/orcid-java-client

README.md
... ... @@ -0,0 +1,275 @@
  1 +# JAVA-ORCID-CLIENT
  2 +
  3 +Simple, easy to use ORCiD client written in Java. Supports the public and Tier2 API with OAuth. Natural object mapping - The entire ORCiD message schema is represented as a hirearchical graph of POJOs with JAXB support for serialisation.
  4 +This work is based on Tom Demeranville Orcid Java Client that is available at [GitHub](https://github.com/TomDemeranville/orcid-java-client)
  5 +
  6 +# Build .jar client
  7 +
  8 +You should use maven, version 3, to build the package.
  9 +
  10 + mvn clean package
  11 +
  12 +A new jar file will be generated on ./target directory:
  13 +
  14 + degois-orcid-client-2.0-rc1.jar
  15 +
  16 +This jar will include the source code as well as will build all POJOs classes based on XSD schema files using JAXB.
  17 +
  18 +
  19 +# Requirements to use this client in your project
  20 +
  21 +## Maven dependencies you will require
  22 +
  23 +In Maven <properties> section you must indicate the versions of the dependencies
  24 +
  25 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  26 + <java.version>1.8</java.version>
  27 + <jersey.version>2.22.1</jersey.version>
  28 + <jaxb2-basics.version>0.9.5</jaxb2-basics.version>
  29 + <log4j.version>2.4</log4j.version>
  30 +
  31 +
  32 +In Maven <dependencies> section you must include the log4j, jersey client, jaxb, javax dependencies in your project
  33 +
  34 + <!-- Log4J -->
  35 + <dependency>
  36 + <groupId>org.apache.logging.log4j</groupId>
  37 + <artifactId>log4j-core</artifactId>
  38 + <version>${log4j.version}</version>
  39 + </dependency>
  40 +
  41 + <!-- Jersey Client -->
  42 + <dependency>
  43 + <groupId>org.glassfish.jersey.core</groupId>
  44 + <artifactId>jersey-client</artifactId>
  45 + <version>${jersey.version}</version>
  46 + </dependency>
  47 + <dependency>
  48 + <groupId>org.glassfish.jersey.containers</groupId>
  49 + <artifactId>jersey-container-servlet</artifactId>
  50 + <version>${jersey.version}</version>
  51 + </dependency>
  52 + <dependency>
  53 + <groupId>org.glassfish.jersey.media</groupId>
  54 + <artifactId>jersey-media-json-jackson</artifactId>
  55 + <version>${jersey.version}</version>
  56 + </dependency>
  57 + <dependency>
  58 + <groupId>org.glassfish.jersey.media</groupId>
  59 + <artifactId>jersey-media-jaxb</artifactId>
  60 + <version>${jersey.version}</version>
  61 + </dependency>
  62 +
  63 + <!-- JAXB2 Commons -->
  64 + <dependency>
  65 + <groupId>org.jvnet.jaxb2_commons</groupId>
  66 + <artifactId>jaxb2-basics-runtime</artifactId>
  67 + <version>${jaxb2-basics.version}</version>
  68 + </dependency>
  69 +
  70 + <!-- javax -->
  71 + <dependency>
  72 + <groupId>javax.servlet</groupId>
  73 + <artifactId>javax.servlet-api</artifactId>
  74 + <version>3.1.0</version>
  75 + <scope>provided</scope>
  76 + </dependency>
  77 + <dependency>
  78 + <groupId>javax.ws.rs</groupId>
  79 + <artifactId>javax.ws.rs-api</artifactId>
  80 + <version>2.0.1</version>
  81 + </dependency>
  82 +
  83 +
  84 +## Maven deploy
  85 +
  86 +It will deploy your jar into your localhost /tmp/repo path:
  87 +
  88 + mvn deploy:deploy-file -Durl=file:///tmp/repo/ \
  89 + -DrepositoryId=localhost \
  90 + -Dfile=target/degois-orcid-client-2.0-rc1.jar \
  91 + -DpomFile=pom.xml
  92 +
  93 +
  94 +## Java imports in your project
  95 +
  96 +You should import:
  97 +
  98 + // Import the client
  99 + import org.um.dsi.gavea.orcid.client.OrcidOAuthClient;
  100 + import org.um.dsi.gavea.orcid.client.OrcidAccessToken;
  101 + import org.um.dsi.gavea.orcid.client.exception.OrcidClientException;
  102 +
  103 + // Import activities
  104 + import org.um.dsi.gavea.orcid.model.activities.ActivitiesSummary;
  105 + import org.um.dsi.gavea.orcid.model.activities.Identifier;
  106 + import org.um.dsi.gavea.orcid.model.activities.WorkGroup;
  107 +
  108 + // Import Works
  109 + import org.um.dsi.gavea.orcid.model.work.ExternalIdentifier;
  110 + import org.um.dsi.gavea.orcid.model.work.ExternalIdentifierType;
  111 + import org.um.dsi.gavea.orcid.model.work.Work;
  112 + import org.um.dsi.gavea.orcid.model.work.WorkExternalIdentifiers;
  113 + import org.um.dsi.gavea.orcid.model.work.WorkTitle;
  114 + import org.um.dsi.gavea.orcid.model.work.WorkType;
  115 +
  116 + // Import Enum types
  117 + import org.um.dsi.gavea.orcid.model.common.RelationshipType;
  118 + import org.um.dsi.gavea.orcid.model.common.ScopePathType;
  119 +
  120 +
  121 +# Usage Examples
  122 +
  123 +## Generate an Access Token, using the sandbox
  124 + String loginUri = "https://sandbox.orcid.org";
  125 + String clientSecret = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
  126 + String clientId = "XXXX-XXXX-XXXX-XXXX";
  127 + String apiUri = "https://api.sandbox.orcid.org";
  128 + //Use google OAUTH playground, this should be the landing page used to receive the Authorization Code
  129 + String redirectUri = "https://developers.google.com/oauthplayground";
  130 +
  131 + // This scopes will allow you to do almost anything to the user profile
  132 + // You should limit the scopes you want to use
  133 + List<ScopePathType> scopes = new ArrayList<ScopePathType>();
  134 + scopes.add(ScopePathType.AUTHENTICATE);
  135 + scopes.add(ScopePathType.ORCID_PROFILE_READ_LIMITED);
  136 + scopes.add(ScopePathType.ACTIVITIES_UPDATE);
  137 + scopes.add(ScopePathType.ORCID_BIO_UPDATE);
  138 +
  139 + // Instantiate the Orcid Client
  140 + OrcidOAuthClient orcidClient = new OrcidOAuthClient(loginUri, apiUri, clientId, clientSecret, redirectUri);
  141 +
  142 + try {
  143 + String authorizationURI = orcidClient.getAuthorizeUriLogin(scopes,state,orcid);
  144 + System.out.println(authorizationURI);
  145 + } catch (Exception e) {
  146 + // TODO Auto-generated catch block
  147 + e.printStackTrace();
  148 + }
  149 +
  150 +Then you should have a landing page in your project, configured in redirectUri to get the Authentication Code.
  151 +
  152 + OrcidAccessToken orcidToken;
  153 +
  154 + try {
  155 + orcidToken = orcidClient.getAccessTokens(authorizationCode);
  156 + accessToken = orcidToken.getAccess_token();
  157 + System.out.println(accessToken);
  158 +
  159 + } catch (OrcidClientException e) {
  160 + // TODO Auto-generated catch block
  161 + e.printStackTrace();
  162 + }
  163 +
  164 +if you already have a token, you could simply use setAccess_token method in the OrcidAccessToken object:
  165 +
  166 + OrcidAccessToken orcidToken = new OrcidAccessToken();
  167 + orcidToken.setAccess_token("d3c1edb9-5385-4b76-af77-e3cd9889c5ec");
  168 +
  169 +## Get activities
  170 +
  171 +To access Activities the token must be associated with the scope /orcid-profile/read-limited
  172 +
  173 + try {
  174 + ActivitiesSummary activities = orcidClient.readActivitiesSummary(orcidToken);
  175 + List<WorkGroup> workGroupList = activities.getWorks().getGroup();
  176 +
  177 + for (WorkGroup workGroup : workGroupList) {
  178 + System.out.print("PUTCODE: " + workGroup.getWorkSummary().get(0).getPutCode() + " - ");
  179 + System.out.println(workGroup.getWorkSummary().get(0).getTitle().getTitle());
  180 +
  181 + List<Identifier> identifiersList = workGroup.getIdentifiers().getIdentifier();
  182 + for (Identifier identifier: identifiersList) {
  183 + //print ID_TYPE: ID_VALUE
  184 + System.out.print(identifier.getExternalIdentifierType() +": " + identifier.getExternalIdentifierId()+"\n");
  185 + }
  186 + }
  187 + } catch (OrcidClientException e) {
  188 + // TODO Auto-generated catch block
  189 + e.printStackTrace();
  190 + }
  191 +
  192 +The output will be:
  193 +
  194 + PUTCODE: 465120 - Organic matter composition and macrofaunal diversity in sediments of the Condor Seamount (Azores, {NE} Atlantic)
  195 + doi: http://dx.doi.org/10.1016/j.dsr2.2013.08.006
  196 + PUTCODE: 468006 - A complex picture of associations between two host mussels and symbiotic bacteria in the Northeast Atlantic
  197 + uri: http://hdl.handle.net/123456789/1154
  198 + PUTCODE: 477773 - Shape analysis of an adaptive elastic rod model
  199 + uri: http://hdl.handle.net/10400.19/2601
  200 + doi: 10.1137/040604443
  201 + PUTCODE: 477774 - Early skin immunological disturbance after Plasmodium-infected mosquito bites
  202 + uri: http://hdl.handle.net/10400.7/254
  203 +
  204 +
  205 +## Get a Work by PUTCODE
  206 +
  207 + try {
  208 + String putCode = "477804";
  209 +
  210 + Work work = orcidClient.readWork(orcidToken, putCode);
  211 + } catch (OrcidClientException e) {
  212 + // TODO Auto-generated catch block
  213 + e.printStackTrace();
  214 + }
  215 +
  216 +## Update a Work
  217 +
  218 +To update a work the token used must be associated with one of the scopes: /activities/update or /orcid-works/update
  219 +
  220 + try {
  221 + String putCode = "477804";
  222 +
  223 + Work work = orcidClient.readWork(orcidToken, putCode);
  224 + WorkTitle workTitle = new WorkTitle("Changed title regarding PTCRISSync",null,null);
  225 + work.setTitle(workTitle);
  226 +
  227 + //Save work with changed title
  228 + orcidClient.updateWork(orcidToken2, putCode, work);
  229 + System.out.println("\n\nSaved with title: " + workTitle.getTitle());
  230 +
  231 + } catch (OrcidClientException e) {
  232 + // TODO Auto-generated catch block
  233 + e.printStackTrace();
  234 + }
  235 +
  236 +## Create a new Work
  237 +
  238 +To create a new work the token used must be associated with one of the scopes: /activities/update or /orcid-works/create
  239 +
  240 + Work newWork = new Work();
  241 +
  242 + // Set the title
  243 + WorkTitle workTitle2 = new WorkTitle("new item PTCRISSync",null,null);
  244 + newWork.setTitle(workTitle2);
  245 +
  246 + // Set the type
  247 + newWork.setType(WorkType.JOURNAL_ARTICLE);
  248 +
  249 + // Set External ID (ORCID API requires at least one)
  250 + ExternalIdentifier internalId = new ExternalIdentifier();
  251 + internalId.setExternalIdentifierType(ExternalIdentifierType.SOURCE_WORK_ID);
  252 + internalId.setExternalIdentifierId("PTCRIS_01");
  253 + // You must indicate the Relationship or the External URL
  254 + internalId.setRelationship(RelationshipType.SELF);
  255 +
  256 + // Set the External Identifiers
  257 + WorkExternalIdentifiers externalIdentifiers = new WorkExternalIdentifiers();
  258 + externalIdentifiers.getWorkExternalIdentifier().add(internalId);
  259 + newWork.setExternalIdentifiers(externalIdentifiers);
  260 +
  261 + try {
  262 +
  263 + //The method addWork will retrieve the PUTCODE
  264 + String newPutCode = orcidClient.addWork(orcidToken2, newWork);
  265 + System.out.println("New item with PUTCODE: " + newPutCode);
  266 +
  267 + } catch (OrcidClientException e) {
  268 + // TODO Auto-generated catch block
  269 + e.printStackTrace();
  270 + }
  271 +
  272 +
  273 +# License
  274 +
  275 +Please contact us.
0 276 \ No newline at end of file
... ...
src/main/java/org/um/dsi/gavea/orcid/client/BaseOrcidOAuthClient.java
... ... @@ -44,26 +44,13 @@ public class BaseOrcidOAuthClient implements Serializable {
44 44 this.clientSecret = clientSecret;
45 45 this.redirectUri = redirectUri;
46 46 }
47   -
48   - protected <T> Response post(final String authorizationCode, final MultivaluedMap<String, String> formData) throws OrcidClientException {
49   - createConnection(OrcidConstants.ENDPOINT_OAUTH_TOKEN, null, null);
50   -
51   - Response response = target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.form(formData));
52   - _log.debug("[getAccessTokens].[Response.Status] " + response.getStatus());
53   - _log.debug("[getAccessTokens].[Response.Reason] " + response.getStatusInfo().getReasonPhrase());
54   -
55   - exceptionBuilder(response);
56   -
57   - return response;
58   - }
59   -
  47 +
60 48 protected <T> Response get(final String endpoint, final OrcidAccessToken token, final String putCode) throws OrcidClientException {
61   - Response response;
  49 + Response response = null;
62 50 try {
63 51 createConnection(endpoint, token.getOrcid(), putCode);
64 52  
65   - response = target.request(OrcidConstants.APPLICATION_ORCID_XML)
66   - .header("Authorization", "Bearer" + token.getAccess_token()).get();
  53 + response = target.request(OrcidConstants.APPLICATION_ORCID_XML).header("Authorization", "Bearer" + token.getAccess_token()).get();
67 54 _log.debug("[get].[Response.Status] " + response.getStatus());
68 55 _log.debug("[get].[Response.Reason] " + response.getStatusInfo().getReasonPhrase());
69 56  
... ... @@ -76,6 +63,18 @@ public class BaseOrcidOAuthClient implements Serializable {
76 63 return response;
77 64 }
78 65  
  66 + protected <T> Response post(final String authorizationCode, final MultivaluedMap<String, String> formData) throws OrcidClientException {
  67 + createConnection(OrcidConstants.ENDPOINT_OAUTH_TOKEN, null, null);
  68 +
  69 + Response response = target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.form(formData));
  70 + _log.debug("[getAccessTokens].[Response.Status] " + response.getStatus());
  71 + _log.debug("[getAccessTokens].[Response.Reason] " + response.getStatusInfo().getReasonPhrase());
  72 +
  73 + exceptionBuilder(response);
  74 +
  75 + return response;
  76 + }
  77 +
79 78 protected <T> Response post(final String endpoint, final OrcidAccessToken token, final Entity<T> entity) throws OrcidClientException {
80 79 Response response;
81 80 try {
... ... @@ -133,15 +132,13 @@ public class BaseOrcidOAuthClient implements Serializable {
133 132 return response;
134 133 }
135 134  
136   -
137 135 private void createConnection(final String endpoint, final String orcidId, final String putCode) {
138   - if (client != null)
139   - client.close();
140   -
141   - client = ClientBuilder.newClient();
142   - client.property(ClientProperties.CONNECT_TIMEOUT, OrcidConstants.CLIENT_CONNECT_TIMEOUT);
143   - client.property(ClientProperties.READ_TIMEOUT, OrcidConstants.CLIENT_READ_TIMEOUT);
144   -
  136 + if (client == null) {
  137 + client = ClientBuilder.newClient();
  138 + client.property(ClientProperties.CONNECT_TIMEOUT, OrcidConstants.CLIENT_CONNECT_TIMEOUT);
  139 + client.property(ClientProperties.READ_TIMEOUT, OrcidConstants.CLIENT_READ_TIMEOUT);
  140 + }
  141 +
145 142 target = client.target(apiUri).path(buildPath(endpoint, orcidId, putCode));
146 143 }
147 144  
... ...
src/main/java/org/um/dsi/gavea/orcid/client/OrcidOAuthClient.java
... ... @@ -29,32 +29,28 @@ public class OrcidOAuthClient extends BaseOrcidOAuthClient {
29 29 }
30 30  
31 31  
32   - public String getAuthorizeUriLogin(final List<ScopePathType> scopes, final String state, final String orcidOrEmail)
33   - throws Exception {
  32 + public String getAuthorizeUriLogin(final List<ScopePathType> scopes, final String state, final String orcidOrEmail) throws Exception {
34 33  
35 34 String orcidId = null;
36 35 String email = null;
37   - if (orcidOrEmail != null && !"".equals(orcidOrEmail)) {
38   - if (isValidOrcidId(orcidOrEmail)) {
  36 + if(orcidOrEmail != null && !"".equals(orcidOrEmail)) {
  37 + if(isValidOrcidId(orcidOrEmail))
39 38 orcidId = orcidOrEmail;
40   - } else {
  39 + else
41 40 email = orcidOrEmail;
42   - }
43 41 }
44 42  
45 43 return getAuthorizeUri(scopes, state, orcidId, null, null, email, null, true);
46 44 }
47 45  
48   - public String getAuthorizeUriRegistration(final List<ScopePathType> scopes, final String state,
49   - final String familyNames, final String givenNames) throws Exception {
  46 + public String getAuthorizeUriRegistration(final List<ScopePathType> scopes, final String state, final String familyNames, final String givenNames) throws Exception {
50 47 return getAuthorizeUri(scopes, state, null, familyNames, givenNames, null, null, false);
51 48 }
52 49  
53   - private String getAuthorizeUri(final List<ScopePathType> scopes, final String state, final String orcidId,
54   - final String familyNames, final String givenNames, final String email, final String lang,
  50 + private String getAuthorizeUri(final List<ScopePathType> scopes, final String state, final String orcidId, final String familyNames, final String givenNames, final String email, final String lang,
55 51 final boolean login) throws Exception {
56 52  
57   - if (scopes == null)
  53 + if(scopes == null)
58 54 throw new Exception("Cannot create Authorize Uri - missing scopes");
59 55  
60 56 UriBuilder builder = UriBuilder.fromUri(loginUri);
... ... @@ -106,70 +102,122 @@ public class OrcidOAuthClient extends BaseOrcidOAuthClient {
106 102  
107 103 /* Activities */
108 104 public ActivitiesSummary readActivitiesSummary(final OrcidAccessToken token) throws OrcidClientException {
109   - return get(OrcidConstants.ENDPOINT_ACTIVITIES, token, null).readEntity(ActivitiesSummary.class);
  105 + Response response = null;
  106 + try {
  107 + response = get(OrcidConstants.ENDPOINT_ACTIVITIES, token, null);
  108 +
  109 + return response.readEntity(ActivitiesSummary.class);
  110 + } finally {
  111 + if(response != null)
  112 + response.close();
  113 + }
110 114 }
111 115  
112 116  
113 117 /* Funding */
114 118 public Funding readFunding(final OrcidAccessToken token, final String putCode) throws OrcidClientException {
115   - return get(OrcidConstants.ENDPOINT_FUNDING, token, putCode).readEntity(Funding.class);
  119 + Response response = null;
  120 + try {
  121 + response = get(OrcidConstants.ENDPOINT_FUNDING, token, putCode);
  122 +
  123 + return response.readEntity(Funding.class);
  124 + } finally {
  125 + if(response != null)
  126 + response.close();
  127 + }
116 128 }
117 129  
118   - public String addFunding(final OrcidAccessToken token, final Funding funding)
119   - throws OrcidClientException {
120   - Response response = post(OrcidConstants.ENDPOINT_FUNDING, token, Entity.entity(funding, MediaType.APPLICATION_XML_TYPE));
121   -
122   - String location = response.getLocation().toString();
123   - if (location != null && !"".equals(location)) {
124   - String putCode = location.substring(location.lastIndexOf("/") + 1, location.length());
125   - if (putCode.matches("\\d+")) {
126   - return putCode;
  130 + public String addFunding(final OrcidAccessToken token, final Funding funding) throws OrcidClientException {
  131 + Response response = null;
  132 + try {
  133 + response = post(OrcidConstants.ENDPOINT_FUNDING, token, Entity.entity(funding, MediaType.APPLICATION_XML_TYPE));
  134 +
  135 + String location = response.getLocation().toString();
  136 + if(location != null && !"".equals(location)) {
  137 + String putCode = location.substring(location.lastIndexOf("/") + 1, location.length());
  138 + if(putCode.matches("\\d+"))
  139 + return putCode;
127 140 }
  141 + } finally {
  142 + if(response != null)
  143 + response.close();
128 144 }
129 145  
130 146 return null;
131 147 }
132 148  
133   - public void updateFunding(final OrcidAccessToken token, final String putCode, final Funding funding)
134   - throws OrcidClientException {
135   - put(OrcidConstants.ENDPOINT_FUNDING, token, putCode, Entity.entity(funding, MediaType.APPLICATION_XML_TYPE));
  149 + public void updateFunding(final OrcidAccessToken token, final String putCode, final Funding funding) throws OrcidClientException {
  150 + Response response = null;
  151 + try {
  152 + response = put(OrcidConstants.ENDPOINT_FUNDING, token, putCode, Entity.entity(funding, MediaType.APPLICATION_XML_TYPE));
  153 + } finally {
  154 + if(response != null)
  155 + response.close();
  156 + }
136 157 }
137 158  
138 159 public void deleteFunding(final OrcidAccessToken token, final String putCode) throws OrcidClientException {
139   - delete(OrcidConstants.ENDPOINT_FUNDING, token, putCode);
  160 + Response response = null;
  161 + try {
  162 + response = delete(OrcidConstants.ENDPOINT_FUNDING, token, putCode);
  163 + } finally {
  164 + if(response != null)
  165 + response.close();
  166 + }
140 167 }
141 168  
142 169  
143 170 /* Work */
144 171 public Work readWork(final OrcidAccessToken token, final String putCode) throws OrcidClientException {
145   - return get(OrcidConstants.ENDPOINT_WORK, token, putCode).readEntity(Work.class);
  172 + Response response = null;
  173 + try {
  174 + response = get(OrcidConstants.ENDPOINT_WORK, token, putCode);
  175 +
  176 + return response.readEntity(Work.class);
  177 + } finally {
  178 + if(response != null)
  179 + response.close();
  180 + }
146 181 }
147 182  
148   - public String addWork(final OrcidAccessToken token, final Work work)
149   - throws OrcidClientException {
150   - Response response = post(OrcidConstants.ENDPOINT_WORK, token, Entity.entity(work, MediaType.APPLICATION_XML_TYPE));
151   -
152   - String location = response.getLocation().toString();
153   - if (location != null && !"".equals(location)) {
154   - String putCode = location.substring(location.lastIndexOf("/") + 1, location.length());
155   - if (putCode.matches("\\d+")) {
156   - return putCode;
  183 + public String addWork(final OrcidAccessToken token, final Work work) throws OrcidClientException {
  184 + Response response = null;
  185 + try {
  186 + response = post(OrcidConstants.ENDPOINT_WORK, token, Entity.entity(work, MediaType.APPLICATION_XML_TYPE));
  187 + String location = response.getLocation().toString();
  188 + if (location != null && !"".equals(location)) {
  189 + String putCode = location.substring(location.lastIndexOf("/") + 1, location.length());
  190 + if (putCode.matches("\\d+"))
  191 + return putCode;
157 192 }
  193 + } finally {
  194 + if(response != null)
  195 + response.close();
158 196 }
159 197  
160 198 return null;
161 199 }
162 200  
163   - public void updateWork(final OrcidAccessToken token, final String putCode, final Work work)
164   - throws OrcidClientException {
165   - put(OrcidConstants.ENDPOINT_WORK, token, putCode, Entity.entity(work, MediaType.APPLICATION_XML_TYPE));
  201 + public void updateWork(final OrcidAccessToken token, final String putCode, final Work work) throws OrcidClientException {
  202 + Response response = null;
  203 + try {
  204 + response = put(OrcidConstants.ENDPOINT_WORK, token, putCode, Entity.entity(work, MediaType.APPLICATION_XML_TYPE));
  205 + } finally {
  206 + if(response != null)
  207 + response.close();
  208 + }
166 209 }
167 210  
168 211 public void deleteWork(final OrcidAccessToken token, final String putCode) throws OrcidClientException {
169   - delete(OrcidConstants.ENDPOINT_WORK, token, putCode);
  212 + Response response = null;
  213 + try {
  214 + response = delete(OrcidConstants.ENDPOINT_WORK, token, putCode);
  215 + } finally {
  216 + if(response != null)
  217 + response.close();
  218 + }
170 219 }
171 220  
172   -
173 221 private boolean isValidOrcidId(final String value) {
174 222 return value.matches("([0-9]{4})-([0-9]{4})-([0-9]{4})-([0-9]{3})(?:[0-9X]{1})");
175 223 }
... ...