Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a /properties endpoint, with the ability to configure which pro… #1471

Merged
merged 8 commits into from
Oct 31, 2017
4 changes: 4 additions & 0 deletions example/road-traffic/road-traffic-demo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
</webapp>
</webapps>
<systemProperties>
<gaffer.properties>gaffer.properties.app.description,</gaffer.properties>
<gaffer.properties.app.description>
Road Traffic Example
</gaffer.properties.app.description>
<gaffer.rest-api.basePath>
${standalone-path}
</gaffer.rest-api.basePath>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public final class ServiceConstants {

public static final String CLASS_NOT_FOUND = "Class not found";
public static final String FUNCTION_NOT_FOUND = "Function not found";
public static final String PROPERTY_NOT_FOUND = "Property not found";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a duplicated line?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They look like different lines to me - one is used when a Function isn't found and one is used when a Property is not found.


public static final String OPERATION_NOT_FOUND = "Operation not found";
public static final String OPERATION_NOT_IMPLEMENTED = "The requested operation is not supported by the target store";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import uk.gov.gchq.gaffer.rest.service.v2.GraphConfigurationServiceV2;
import uk.gov.gchq.gaffer.rest.service.v2.JobServiceV2;
import uk.gov.gchq.gaffer.rest.service.v2.OperationServiceV2;
import uk.gov.gchq.gaffer.rest.service.v2.PropertiesServiceV2;
import uk.gov.gchq.gaffer.rest.service.v2.StatusServiceV2;
import uk.gov.gchq.gaffer.rest.service.v2.example.ExampleBinder;
import uk.gov.gchq.gaffer.rest.service.v2.example.ExamplesServiceV2;
Expand Down Expand Up @@ -68,6 +69,7 @@ protected void addServices() {
resources.add(GraphConfigurationServiceV2.class);
resources.add(JobServiceV2.class);
resources.add(ExamplesServiceV2.class);
resources.add(PropertiesServiceV2.class);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2016-2017 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.gov.gchq.gaffer.rest.service.v2;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import java.util.Map;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static uk.gov.gchq.gaffer.rest.ServiceConstants.INTERNAL_SERVER_ERROR;
import static uk.gov.gchq.gaffer.rest.ServiceConstants.OK;
import static uk.gov.gchq.gaffer.rest.ServiceConstants.PROPERTY_NOT_FOUND;

/**
* An {@code IPropertiesServiceV2} has methods to GET a list of configured system properties
*/
@Path("/properties")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
@Api(value = "properties")
public interface IPropertiesServiceV2 {

@GET
@Path("/")
@ApiOperation(value = "Gets all available properties", response = Map.class, produces = APPLICATION_JSON)
@ApiResponses(value = {@ApiResponse(code = 200, message = OK), @ApiResponse(code = 500, message = INTERNAL_SERVER_ERROR)})
Response getProperties();

@GET
@Path("/{propertyName}")
@Produces(TEXT_PLAIN)
@ApiOperation(value = "Gets the property value for the specified property name.", response = String.class, produces = TEXT_PLAIN)
@ApiResponses(value = {@ApiResponse(code = 200, message = OK),
@ApiResponse(code = 404, message = PROPERTY_NOT_FOUND),
@ApiResponse(code = 500, message = INTERNAL_SERVER_ERROR)})
Response getProperty(@ApiParam(value = "the property name") @PathParam("propertyName") final String propertyName);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2016-2017 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.gov.gchq.gaffer.rest.service.v2;

import uk.gov.gchq.gaffer.rest.ServiceConstants;

import javax.ws.rs.core.Response;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
* An implementation of {@link IPropertiesServiceV2} that gets the configured system properties
*/
public class PropertiesServiceV2 implements IPropertiesServiceV2 {
private static final Map<String, String> PROPERTIES = new HashMap<>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be better to not cache the properties in case any of the properties change over time. In the future, if we find it is really slow then we could consider adding a daily cache or something similar.

private static final String PROPERTIES_LIST = "gaffer.properties";

static {
String properties = System.getProperty(PROPERTIES_LIST);
if (properties != null) {
String[] props = properties.split(",");
for (final String prop : props) {
PROPERTIES.put(prop, System.getProperty(prop));
}
}
}

@Override
public Response getProperties() {
return Response.ok(Collections.unmodifiableMap(PROPERTIES))
.header(ServiceConstants.GAFFER_MEDIA_TYPE_HEADER, ServiceConstants.GAFFER_MEDIA_TYPE).build();
}

@Override
public Response getProperty(final String propertyName) {
String prop = PROPERTIES.get(propertyName);
return prop == null ? Response.status(404).header(ServiceConstants.GAFFER_MEDIA_TYPE_HEADER, ServiceConstants.GAFFER_MEDIA_TYPE).build() : Response.ok(prop).header(ServiceConstants.GAFFER_MEDIA_TYPE_HEADER, ServiceConstants.GAFFER_MEDIA_TYPE).build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public abstract class AbstractRestApiIT {
public abstract class AbstractRestApiIT<T extends RestApiTestClient> {
protected static final Element[] DEFAULT_ELEMENTS = {
new uk.gov.gchq.gaffer.data.element.Entity.Builder()
.group(TestGroups.ENTITY)
Expand All @@ -56,7 +56,7 @@ public abstract class AbstractRestApiIT {
.build()};
@Rule
public final TemporaryFolder testFolder = new TemporaryFolder(CommonTestConstants.TMP_DIRECTORY);
protected final RestApiTestClient client = getClient();
protected final T client = getClient();
private final String storePropertiesResourcePath;
private final String schemaResourcePath;

Expand Down Expand Up @@ -85,5 +85,5 @@ protected void verifyElements(final Element[] expected, final List<Element> actu
assertThat(actual, IsCollectionContaining.hasItems(expected));
}

protected abstract RestApiTestClient getClient();
protected abstract T getClient();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
import uk.gov.gchq.gaffer.rest.AbstractRestApiIT;
import uk.gov.gchq.gaffer.rest.RestApiTestClient;

public class AbstractRestApiV1IT extends AbstractRestApiIT {
public class AbstractRestApiV1IT extends AbstractRestApiIT<RestApiV1TestClient> {

@Override
protected RestApiTestClient getClient() {
protected RestApiV1TestClient getClient() {
return new RestApiV1TestClient();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
import uk.gov.gchq.gaffer.rest.AbstractRestApiIT;
import uk.gov.gchq.gaffer.rest.RestApiTestClient;

public class AbstractRestApiV2IT extends AbstractRestApiIT {
public class AbstractRestApiV2IT extends AbstractRestApiIT<RestApiV2TestClient> {

@Override
protected RestApiTestClient getClient() {
protected RestApiV2TestClient getClient() {
return new RestApiV2TestClient();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package uk.gov.gchq.gaffer.rest.service.v2;
/*
* Copyright 2017 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.junit.Test;

import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.Map;

import static org.junit.Assert.assertEquals;

public class PropertyServiceV2IT extends AbstractRestApiV2IT {

@Test
public void shouldThrowErrorOnUnknownPropertyWhenNoneSet() throws IOException {
//Given

// When
final Response response = getClient().getProperty("UNKNOWN");

//Then
assertEquals(404, response.getStatus());
}

@Test
public void shouldThrowErrorOnUnknownProperty() throws IOException {
//Given
System.setProperty("gaffer.properties", "gaffer.test1,gaffer.test2");
System.setProperty("gaffer.test1", "1");
System.setProperty("gaffer.test2", "3");

// When
final Response response = getClient().getProperty("UNKNOWN");

//Then
assertEquals(404, response.getStatus());
}

@Test
public void shouldGetAllProperties() throws IOException {
//Given
System.setProperty("gaffer.properties", "gaffer.test1,gaffer.test2");
System.setProperty("gaffer.test1", "1");
System.setProperty("gaffer.test2", "3");
// When
final Response response = getClient().getProperties();

//Then
assertEquals(200, response.getStatus());
Map<String, Object> properties = response.readEntity(Map.class);
assertEquals(2, properties.size());
assertEquals("1", properties.get("gaffer.test1"));
assertEquals("3", properties.get("gaffer.test2"));
}

@Test
public void shouldGetKnownProperty() throws IOException {
//Given
System.setProperty("gaffer.properties", "gaffer.test1,gaffer.test2");
System.setProperty("gaffer.test1", "1");
System.setProperty("gaffer.test2", "3");
// When
final Response response = getClient().getProperty("gaffer.test1");

//Then
assertEquals(200, response.getStatus());
String property = response.readEntity(String.class);
assertEquals("1", property);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,18 @@ public SystemStatus getRestServiceStatus() {
.request()
.get(SystemStatus.class);
}

public Response getProperties() {
return client.target(uriString)
.path("/properties")
.request()
.get(Response.class);
}

public Response getProperty(String property) {
return client.target(uriString)
.path("/properties/" + property)
.request()
.get(Response.class);
}
}