diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/Application.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/Application.java
index c810835391..892bc7afa7 100644
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/Application.java
+++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/Application.java
@@ -2,14 +2,19 @@
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
- *
+ *
* http://www.dspace.org/license/
*/
package org.dspace.app.rest;
+import java.io.File;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.servlet.Filter;
+
import org.dspace.app.rest.filter.DSpaceRequestContextFilter;
import org.dspace.app.rest.model.hateoas.DSpaceRelProvider;
-import org.dspace.app.rest.parameter.resolver.SearchFilterResolver;
import org.dspace.app.rest.utils.ApplicationConfig;
import org.dspace.app.util.DSpaceContextListener;
import org.dspace.kernel.DSpaceKernel;
@@ -28,11 +33,12 @@ import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationListener;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.core.annotation.Order;
import org.springframework.hateoas.RelProvider;
-import org.springframework.web.method.support.HandlerMethodArgumentResolver;
+import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@@ -59,16 +65,12 @@ import java.io.File;
*/
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
+
private static final Logger log = LoggerFactory.getLogger(Application.class);
@Autowired
private ApplicationConfig configuration;
- @Value("${dspace.dir}")
- private String dspaceHome;
-
- private transient DSpaceKernelImpl kernelImpl;
-
/**
* Override the default SpringBootServletInitializer.configure() method,
* passing it this Application class.
@@ -84,6 +86,9 @@ public class Application extends SpringBootServletInitializer {
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(Application.class)
+ .initializers(new DSpaceKernelInitializer());
+ }
// start the kernel when the webapp starts
try {
@@ -112,14 +117,7 @@ public class Application extends SpringBootServletInitializer {
@Bean
public ServletContextInitializer contextInitializer() {
- return new ServletContextInitializer() {
-
- @Override
- public void onStartup(ServletContext servletContext)
- throws ServletException {
- servletContext.setInitParameter("dspace.dir", configuration.getDspaceHome());
- }
- };
+ return servletContext -> servletContext.setInitParameter("dspace.dir", configuration.getDspaceHome());
}
/**
@@ -171,7 +169,7 @@ public class Application extends SpringBootServletInitializer {
}
@Bean
- public WebMvcConfigurer webMvcConfigurer() {
+ public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
@@ -180,41 +178,10 @@ public class Application extends SpringBootServletInitializer {
registry.addMapping("/api/**").allowedOrigins(corsAllowedOrigins);
}
}
-
- @Override
- public void addArgumentResolvers(List argumentResolvers) {
- argumentResolvers.add(new SearchFilterResolver());
- }
};
}
- /**
- * Find DSpace's "home" directory.
- * Initially look for JNDI Resource called "java:/comp/env/dspace.dir".
- * If not found, look for "dspace.dir" initial context parameter.
- */
- private String getProvidedHome(String dspaceHome) {
- String providedHome = null;
- try {
- Context ctx = new InitialContext();
- providedHome = (String) ctx.lookup("java:/comp/env/" + DSpaceConfigurationService.DSPACE_HOME);
- } catch (Exception e) {
- // do nothing
- }
-
- if (providedHome == null) {
- if (dspaceHome != null && !dspaceHome.equals("") &&
- !dspaceHome.equals("${" + DSpaceConfigurationService.DSPACE_HOME + "}")) {
- File test = new File(dspaceHome);
- if (test.exists() && new File(test, DSpaceConfigurationService.DSPACE_CONFIG_PATH).exists()) {
- providedHome = dspaceHome;
- }
- }
- return providedHome;
- }
- return providedHome;
- }
-
+ /** Utility class that will destroy the DSpace Kernel on Spring Boot shutdown */
private class DSpaceKernelDestroyer implements ApplicationListener {
private DSpaceKernelImpl kernelImpl;
@@ -229,4 +196,67 @@ public class Application extends SpringBootServletInitializer {
}
}
}
+
+ /** Utility class that will initialize the DSpace Kernel on Spring Boot startup */
+ private class DSpaceKernelInitializer implements ApplicationContextInitializer {
+
+ private transient DSpaceKernelImpl kernelImpl;
+
+ public void initialize(final ConfigurableApplicationContext applicationContext) {
+
+ String dspaceHome = applicationContext.getEnvironment().getProperty("dspace.dir");
+
+ // start the kernel when the webapp starts
+ try {
+ this.kernelImpl = DSpaceKernelInit.getKernel(null);
+ if (!this.kernelImpl.isRunning()) {
+ this.kernelImpl.start(getProvidedHome(dspaceHome)); // init the kernel
+ }
+
+ //Set the DSpace Kernel Application context as a parent of the Spring Boot context so that
+ //we can auto-wire all DSpace Kernel services
+ applicationContext.setParent(kernelImpl.getServiceManager().getApplicationContext());
+
+ //Add a listener for Spring Boot application shutdown so that we can nicely cleanup the DSpace kernel.
+ applicationContext.addApplicationListener(new DSpaceKernelDestroyer(kernelImpl));
+
+ } catch (Exception e) {
+ // failed to start so destroy it and log and throw an exception
+ try {
+ this.kernelImpl.destroy();
+ } catch (Exception e1) {
+ // nothing
+ }
+ String message = "Failure during ServletContext initialisation: " + e.getMessage();
+ log.error(message + ":" + e.getMessage(), e);
+ throw new RuntimeException(message, e);
+ }
+ }
+
+ /**
+ * Find DSpace's "home" directory.
+ * Initially look for JNDI Resource called "java:/comp/env/dspace.dir".
+ * If not found, look for "dspace.dir" initial context parameter.
+ */
+ private String getProvidedHome(String dspaceHome) {
+ String providedHome = null;
+ try {
+ Context ctx = new InitialContext();
+ providedHome = (String) ctx.lookup("java:/comp/env/" + DSpaceConfigurationService.DSPACE_HOME);
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ if (providedHome == null) {
+ if (dspaceHome != null && !dspaceHome.equals("") &&
+ !dspaceHome.equals("${" + DSpaceConfigurationService.DSPACE_HOME + "}")) {
+ File test = new File(dspaceHome);
+ if (test.exists() && new File(test, DSpaceConfigurationService.DSPACE_CONFIG_PATH).exists()) {
+ providedHome = dspaceHome;
+ }
+ }
+ }
+ return providedHome;
+ }
+ }
}
\ No newline at end of file
diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java
index ba5718ff13..e5b480a2fb 100644
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java
+++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java
@@ -26,6 +26,7 @@ import org.dspace.app.rest.exception.PaginationException;
import org.dspace.app.rest.exception.RepositoryNotFoundException;
import org.dspace.app.rest.exception.RepositorySearchMethodNotFoundException;
import org.dspace.app.rest.exception.RepositorySearchNotFoundException;
+import org.dspace.app.rest.link.HalLinkService;
import org.dspace.app.rest.model.LinkRest;
import org.dspace.app.rest.model.RestModel;
import org.dspace.app.rest.model.hateoas.DSpaceResource;
@@ -74,6 +75,9 @@ public class RestResourceController implements InitializingBean {
@Autowired
RestRepositoryUtils repositoryUtils;
+ @Autowired
+ HalLinkService linkService;
+
@Override
public void afterPropertiesSet() {
List links = new ArrayList();
@@ -124,6 +128,7 @@ public class RestResourceController implements InitializingBean {
throw new ResourceNotFoundException(apiCategory + "." + model + " with id: " + id + " not found");
}
DSpaceResource result = repository.wrapResource(modelObject);
+ linkService.addLinks(result);
return result;
}
@@ -213,6 +218,8 @@ public class RestResourceController implements InitializingBean {
}
RestModel modelObject = repository.findOne(uuid);
DSpaceResource result = repository.wrapResource(modelObject, rel);
+ linkService.addLinks(result);
+
if (result.getLink(rel) == null) {
// TODO create a custom exception
throw new ResourceNotFoundException(rel + "undefined for " + model);
@@ -251,6 +258,7 @@ public class RestResourceController implements InitializingBean {
Page> resources;
try {
resources = repository.findAll(page).map(repository::wrapResource);
+ resources.forEach(linkService::addLinks);
} catch (PaginationException pe) {
resources = new PageImpl>(new ArrayList>(), page, pe.getTotal());
}
@@ -320,6 +328,7 @@ public class RestResourceController implements InitializingBean {
ResourceSupport result = null;
if (returnPage) {
Page> resources = ((Page) searchResult).map(repository::wrapResource);
+ resources.forEach(linkService::addLinks);
result = assembler.toResource(resources, link);
} else {
result = repository.wrapResource((T) searchResult);
diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/DSpaceResourceHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/DSpaceResourceHalLinkFactory.java
index a5007fbaf9..5811f02e61 100644
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/DSpaceResourceHalLinkFactory.java
+++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/DSpaceResourceHalLinkFactory.java
@@ -7,38 +7,75 @@
*/
package org.dspace.app.rest.link;
-import org.dspace.app.rest.DiscoveryRestController;
-import org.dspace.app.rest.model.hateoas.DSpaceResource;
-import org.dspace.app.rest.model.hateoas.HALResource;
-import org.dspace.app.rest.model.hateoas.SearchConfigurationResource;
-import org.springframework.hateoas.Link;
-import org.springframework.hateoas.Links;
-import org.springframework.stereotype.Component;
-
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
import java.util.LinkedList;
-import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.dspace.app.rest.RestResourceController;
+import org.dspace.app.rest.model.LinkRest;
+import org.dspace.app.rest.model.RestModel;
+import org.dspace.app.rest.model.hateoas.DSpaceResource;
+import org.dspace.app.rest.utils.Utils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.hateoas.Link;
+import org.springframework.stereotype.Component;
/**
* Created by raf on 25/09/2017.
*/
@Component
-public class DSpaceResourceHalLinkFactory extends HalLinkFactory {
+public class DSpaceResourceHalLinkFactory extends HalLinkFactory {
+ @Autowired
+ private Utils utils;
protected void addLinks(DSpaceResource halResource, LinkedList list) {
+ RestModel data = halResource.getData();
+ try {
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(data.getClass()).getPropertyDescriptors()) {
+ Method readMethod = pd.getReadMethod();
+ String name = pd.getName();
+ if (readMethod != null && !"class".equals(name)) {
+ LinkRest linkAnnotation = readMethod.getAnnotation(LinkRest.class);
+
+ if (linkAnnotation != null) {
+ if (StringUtils.isNotBlank(linkAnnotation.name())) {
+ name = linkAnnotation.name();
+ }
+
+ Link linkToSubResource = utils.linkToSubResource(data, name);
+ // no method is specified to retrieve the linked object(s) so check if it is already here
+ if (StringUtils.isBlank(linkAnnotation.method())) {
+ halResource.add(linkToSubResource);
+ }
+
+ } else if (RestModel.class.isAssignableFrom(readMethod.getReturnType())) {
+ Link linkToSubResource = utils.linkToSubResource(data, name);
+ halResource.add(linkToSubResource);
+ }
+ }
+ }
+ } catch (IntrospectionException e) {
+ e.printStackTrace();
+ }
+
+ halResource.add(utils.linkToSingleResource(data, Link.REL_SELF));
}
- protected Class getControllerClass() {
- return null;
+ protected Class getControllerClass() {
+ return RestResourceController.class;
}
protected Class getResourceClass() {
- return null;
+ return DSpaceResource.class;
}
protected String getSelfLink(DSpaceResource halResource) {
- return null;
+ return utils.linkToSingleResource(halResource.getData(), Link.REL_SELF).getHref();
}
}
diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkFactory.java
index 684daa9b4f..5278c8a4b3 100644
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkFactory.java
+++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/HalLinkFactory.java
@@ -7,18 +7,17 @@
*/
package org.dspace.app.rest.link;
+import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
+import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
+
+import java.util.LinkedList;
+import java.util.List;
+
import org.dspace.app.rest.model.hateoas.HALResource;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Objects;
-
-import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
-import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
-
/**
* Created by raf on 25/09/2017.
*/
@@ -26,7 +25,7 @@ import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
public abstract class HalLinkFactory {
public boolean supports(Class clazz) {
- if(Objects.equals(clazz, getResourceClass())){
+ if(getResourceClass().isAssignableFrom(clazz)){
return true;
}
return false;
diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/ItemResourceHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/ItemResourceHalLinkFactory.java
deleted file mode 100644
index 95324dd59b..0000000000
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/ItemResourceHalLinkFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * The contents of this file are subject to the license and copyright
- * detailed in the LICENSE and NOTICE files at the root of the source
- * tree and available online at
- *
- * http://www.dspace.org/license/
- */
-package org.dspace.app.rest.link;
-
-import org.dspace.app.rest.DiscoveryRestController;
-import org.dspace.app.rest.model.hateoas.DSpaceResource;
-import org.dspace.app.rest.model.hateoas.HALResource;
-import org.dspace.app.rest.model.hateoas.ItemResource;
-import org.dspace.app.rest.model.hateoas.SearchConfigurationResource;
-import org.springframework.hateoas.Link;
-import org.springframework.hateoas.Links;
-import org.springframework.stereotype.Component;
-
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Created by raf on 25/09/2017.
- */
-@Component
-public class ItemResourceHalLinkFactory extends HalLinkFactory {
-
- protected void addLinks(ItemResource halResource, LinkedList list) {
-
- }
-
- protected Class getControllerClass() {
- return null;
- }
-
- protected Class getResourceClass() {
- return null;
- }
-
- protected String getSelfLink(ItemResource halResource) {
- return null;
- }
-
-}
diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java
index a1ec4554ee..3dc1e55083 100644
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java
+++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/link/search/SearchSupportHalLinkFactory.java
@@ -7,21 +7,13 @@
*/
package org.dspace.app.rest.link.search;
+import java.util.LinkedList;
+
import org.dspace.app.rest.DiscoveryRestController;
import org.dspace.app.rest.link.HalLinkFactory;
-import org.dspace.app.rest.model.SearchConfigurationRest;
-import org.dspace.app.rest.model.hateoas.HALResource;
-import org.dspace.app.rest.model.hateoas.SearchConfigurationResource;
import org.dspace.app.rest.model.hateoas.SearchSupportResource;
import org.springframework.hateoas.Link;
import org.springframework.stereotype.Component;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
-import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
/**
* Created by raf on 25/09/2017.
@@ -32,7 +24,7 @@ public class SearchSupportHalLinkFactory extends HalLinkFactory list) {
list.add(buildLink(Link.REL_SELF, getMethodOn()
.getSearchSupport(null, null)));
- list.add(buildLink("configuration", getMethodOn().getSearchConfiguration(null, null)));
+ list.add(buildLink("search", getMethodOn().getSearchConfiguration(null, null)));
list.add(buildLink("facets", getMethodOn().getFacetsConfiguration(null, null)));
}
diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java
index 1a2a8330f9..01293df9bf 100644
--- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java
+++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/model/hateoas/DSpaceResource.java
@@ -7,6 +7,16 @@
*/
package org.dspace.app.rest.model.hateoas;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import org.apache.commons.lang3.StringUtils;
import org.dspace.app.rest.model.BaseObjectRest;
@@ -20,16 +30,6 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.hateoas.Link;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
/**
* A base class for DSpace Rest HAL Resource. The HAL Resource wraps the REST
* Resource adding support for the links and embedded resources. Each property
@@ -99,7 +99,6 @@ public abstract class DSpaceResource extends HALResource {
Link linkToSubResource = utils.linkToSubResource(data, name);
// no method is specified to retrieve the linked object(s) so check if it is already here
if (StringUtils.isBlank(linkAnnotation.method())) {
-
Object linkedObject = readMethod.invoke(data);
Object wrapObject = linkedObject;
if (linkedObject instanceof RestModel) {
@@ -168,8 +167,6 @@ public abstract class DSpaceResource extends HALResource {
}
}
else if (RestModel.class.isAssignableFrom(readMethod.getReturnType())) {
- Link linkToSubResource = utils.linkToSubResource(data, name);
- this.add(linkToSubResource);
RestModel linkedObject = (RestModel) readMethod.invoke(data);
if (linkedObject != null) {
embedded.put(name,
@@ -188,15 +185,9 @@ public abstract class DSpaceResource extends HALResource {
| InvocationTargetException e) {
throw new RuntimeException(e.getMessage(), e);
}
- this.add(utils.linkToSingleResource(data, Link.REL_SELF));
}
}
- @Override
- public void add(Link link) {
- System.out.println("Chiamato "+link.getRel());
- super.add(link);
- }
public Map getEmbedded() {
return embedded;
}