DATACMNS-58 - Added support for repository populators.
Added RepositoryPopulator abstraction and implementations based on Spring OXM Unmarshallers as well as Jackson. This allows arbitrary repositories being populated with data pulled from XML / JSON, no matter what store they are actually backed. The populator will eventually populate the repositories held in a Repositories instance. It can be used like this:
Repositories repositories = new Repositories(applicationContext);
ResourceReader reader = new JacksonResourceReader();
ResourceReaderRepositoryPopulator populator = new ResourceReaderRepositoryPopulator(reader);
populator.setResourceLocation("classpath*:data.json");
populator.populate(repositories);
The ResourceReader defines what technology shall be used to read the data from the file into objects. The ResourceReaderRepositoryPopulator uses the reader and can either get a set of Resource instances configured or is able to lookup resources using a location string. The actual Repositories instance captures all CrudRepository instances contained inside an ApplicationContext.
The populators can also be used from within XML configuration though the repository namespace elements shown below:
<repository:jackson-populator location="classpath:org/springframework/data/repository/init/data.json" />
<repository:unmarshaller-populator location="classpath:org/springframework/data/repository/init/data.xml" unmarshaller-ref="unmarshaller" />
Updated reference documentation accordingly.
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
<querydsl.version>2.5.0</querydsl.version>
|
||||
<cdi.version>1.0</cdi.version>
|
||||
<webbeans.version>1.1.3</webbeans.version>
|
||||
<jackson.version>1.9.7</jackson.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -32,6 +33,18 @@
|
||||
<version>${org.springframework.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-oxm</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandler;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* {@link NamespaceHandler} to register {@link BeanDefinitionParser}s for repository initializers.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.4
|
||||
*/
|
||||
public class RepositoryNameSpaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
private static final BeanDefinitionParser PARSER = new ResourceReaderRepositoryPopulatorBeanDefinitionParser();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||
*/
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("unmarshaller-populator", PARSER);
|
||||
registerBeanDefinitionParser("jackson-populator", PARSER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.config;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.data.repository.init.JacksonRepositoryPopulatorFactoryBean;
|
||||
import org.springframework.data.repository.init.UnmarshallerRepositoryPopulatorFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} to parse repository initializers.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ResourceReaderRepositoryPopulatorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClassName(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected String getBeanClassName(Element element) {
|
||||
|
||||
String name = element.getLocalName();
|
||||
return "unmarshaller-populator".equals(name) ? UnmarshallerRepositoryPopulatorFactoryBean.class.getName()
|
||||
: JacksonRepositoryPopulatorFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
String localName = element.getLocalName();
|
||||
|
||||
builder.addPropertyValue("resources", element.getAttribute("locations"));
|
||||
|
||||
if ("unmarshaller-populator".equals(localName)) {
|
||||
parseXmlPopulator(element, builder);
|
||||
} else if ("jackson-populator".equals(localName)) {
|
||||
parseJsonPopulator(element, builder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the {@link BeanDefinitionBuilder} for a Jackson reader.
|
||||
*
|
||||
* @param element
|
||||
* @param builder
|
||||
*/
|
||||
private void parseJsonPopulator(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
String objectMapperRef = element.getAttribute("object-mapper-ref");
|
||||
|
||||
if (StringUtils.hasText(objectMapperRef)) {
|
||||
builder.addPropertyReference("mapper", objectMapperRef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the {@link BeanDefinitionBuilder} for XML reader.
|
||||
*
|
||||
* @param element
|
||||
* @param builder
|
||||
*/
|
||||
private void parseXmlPopulator(Element element, BeanDefinitionBuilder builder) {
|
||||
|
||||
String unmarshallerRefName = element.getAttribute("unmarshaller-ref");
|
||||
|
||||
if (StringUtils.hasText(unmarshallerRefName)) {
|
||||
builder.addPropertyReference("unmarshaller", unmarshallerRefName);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#shouldGenerateIdAsFallback()
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldGenerateIdAsFallback() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} to set up a {@link ResourceReaderRepositoryPopulator} with a {@link JacksonResourceReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class AbstractRepositoryPopulatorFactoryBean extends
|
||||
AbstractFactoryBean<ResourceReaderRepositoryPopulator> implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private Resource[] resources;
|
||||
private RepositoryPopulator populator;
|
||||
|
||||
/**
|
||||
* Configures the {@link Resource}s to be used to load objects from and initialize the repositories eventually.
|
||||
*
|
||||
* @param resources the resources to set
|
||||
*/
|
||||
public void setResources(Resource[] resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return ResourceReaderRepositoryPopulator.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
||||
*/
|
||||
@Override
|
||||
protected ResourceReaderRepositoryPopulator createInstance() throws Exception {
|
||||
|
||||
ResourceReaderRepositoryPopulator initializer = new ResourceReaderRepositoryPopulator(getResourceReader());
|
||||
initializer.setResources(resources);
|
||||
|
||||
this.populator = initializer;
|
||||
|
||||
return initializer;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
|
||||
if (event.equals(getBeanFactory())) {
|
||||
Repositories repositories = new Repositories(event.getApplicationContext());
|
||||
populator.populate(repositories);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ResourceReader getResourceReader();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} to set up a {@link ResourceReaderRepositoryPopulator} with a {@link JacksonResourceReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JacksonRepositoryPopulatorFactoryBean extends AbstractRepositoryPopulatorFactoryBean {
|
||||
|
||||
private ObjectMapper mapper;
|
||||
|
||||
/**
|
||||
* Configures the {@link ObjectMapper} to be used.
|
||||
*
|
||||
* @param mapper
|
||||
*/
|
||||
public void setMapper(ObjectMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.init.AbstractRepositoryPopulatorFactoryBean#getResourceReader()
|
||||
*/
|
||||
@Override
|
||||
protected ResourceReader getResourceReader() {
|
||||
return new JacksonResourceReader(mapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.codehaus.jackson.JsonNode;
|
||||
import org.codehaus.jackson.map.DeserializationConfig.Feature;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A {@link ResourceReader} using Jackson to read JSON into objects.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JacksonResourceReader implements ResourceReader {
|
||||
|
||||
private static final String DEFAULT_TYPE_KEY = "_class";
|
||||
private static final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();
|
||||
|
||||
static {
|
||||
DEFAULT_MAPPER.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
|
||||
private final ObjectMapper mapper;
|
||||
private String typeKey = DEFAULT_TYPE_KEY;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JacksonResourceReader}.
|
||||
*/
|
||||
public JacksonResourceReader() {
|
||||
this(DEFAULT_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link JacksonResourceReader} using the given {@link ObjectMapper}.
|
||||
*
|
||||
* @param mapper
|
||||
*/
|
||||
public JacksonResourceReader(ObjectMapper mapper) {
|
||||
this.mapper = mapper == null ? DEFAULT_MAPPER : mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the JSON document's key to lookup the type to instantiate the object. Defaults to
|
||||
* {@value JacksonResourceReader#DEFAULT_TYPE_KEY}.
|
||||
*
|
||||
* @param typeKey
|
||||
*/
|
||||
public void setTypeKey(String typeKey) {
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.init.ResourceReader#readFrom(org.springframework.core.io.Resource, java.lang.ClassLoader)
|
||||
*/
|
||||
public Object readFrom(Resource resource, ClassLoader classLoader) throws Exception {
|
||||
|
||||
InputStream stream = resource.getInputStream();
|
||||
JsonNode node = mapper.reader(JsonNode.class).readTree(stream);
|
||||
|
||||
if (node.isArray()) {
|
||||
|
||||
Iterator<JsonNode> elements = node.getElements();
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
|
||||
while (elements.hasNext()) {
|
||||
JsonNode element = elements.next();
|
||||
result.add(readSingle(element, classLoader));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return readSingle(node, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given {@link JsonNode} into an instance of the type encoded in it using the configured type key.
|
||||
*
|
||||
* @param node must not be {@literal null}.
|
||||
* @param classLoader
|
||||
* @return
|
||||
*/
|
||||
private Object readSingle(JsonNode node, ClassLoader classLoader) throws IOException {
|
||||
|
||||
JsonNode typeNode = node.findValue(typeKey);
|
||||
String typeName = typeNode == null ? null : typeNode.asText();
|
||||
|
||||
Class<?> type = ClassUtils.resolveClassName(typeName, classLoader);
|
||||
|
||||
return mapper.reader(type).readValue(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
|
||||
/**
|
||||
* Interface for components that will populate the Spring Data repositories with objects.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.4
|
||||
*/
|
||||
public interface RepositoryPopulator {
|
||||
|
||||
/**
|
||||
* Populates the given {@link Repositories}.
|
||||
*
|
||||
* @param repositories
|
||||
*/
|
||||
void populate(Repositories repositories);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface ResourceReader {
|
||||
|
||||
public static enum Type {
|
||||
XML, JSON;
|
||||
}
|
||||
|
||||
Object readFrom(Resource resource, ClassLoader classLoader) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link RepositoryPopulator} using a {@link ResourceReader} to read objects from the configured {@link Resource}
|
||||
* s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.4
|
||||
*/
|
||||
public class ResourceReaderRepositoryPopulator implements RepositoryPopulator {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(ResourceReaderRepositoryPopulator.class);
|
||||
|
||||
private final ResourcePatternResolver resolver;
|
||||
private final ResourceReader reader;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private Collection<Resource> resources;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ResourceReaderRepositoryPopulator} using the given {@link ResourceReader}.
|
||||
*
|
||||
* @param reader must not be {@literal null}.
|
||||
*/
|
||||
public ResourceReaderRepositoryPopulator(ResourceReader reader) {
|
||||
this(reader, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Createsa a new {@link ResourceReaderRepositoryPopulator} using the given {@link ResourceReader} and
|
||||
* {@link ClassLoader}.
|
||||
*
|
||||
* @param reader must not be {@literal null}.
|
||||
* @param classLoader
|
||||
*/
|
||||
public ResourceReaderRepositoryPopulator(ResourceReader resourceReader, ClassLoader classLoader) {
|
||||
|
||||
Assert.notNull(resourceReader);
|
||||
|
||||
this.reader = resourceReader;
|
||||
this.classLoader = classLoader;
|
||||
this.resolver = classLoader == null ? new PathMatchingResourcePatternResolver()
|
||||
: new PathMatchingResourcePatternResolver(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the location of the {@link Resource}s to be used to initialize the repositories.
|
||||
*
|
||||
* @param location must not be {@literal null} or empty.
|
||||
* @throws IOException
|
||||
*/
|
||||
public void setResourceLocation(String location) throws IOException {
|
||||
Assert.hasText(location);
|
||||
setResources(resolver.getResources(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link Resource}s to be used to initialize the repositories.
|
||||
*
|
||||
* @param resources
|
||||
*/
|
||||
public void setResources(Resource... resources) {
|
||||
this.resources = Arrays.asList(resources);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.init.RepositoryPopulator#initialize()
|
||||
*/
|
||||
public void populate(Repositories repositories) {
|
||||
|
||||
for (Resource resource : resources) {
|
||||
|
||||
Object result = readObjectFrom(resource);
|
||||
|
||||
if (result instanceof Collection) {
|
||||
for (Object element : (Collection<?>) result) {
|
||||
if (element != null) {
|
||||
persist(element, repositories);
|
||||
} else {
|
||||
LOG.info("Skipping null element found in unmarshal result!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
persist(result, repositories);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given resource into an {@link Object} using the configured {@link ResourceReader}.
|
||||
*
|
||||
* @param resource must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private Object readObjectFrom(Resource resource) {
|
||||
try {
|
||||
return reader.readFrom(resource, classLoader);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists the given {@link Object} using a suitable repository.
|
||||
*
|
||||
* @param object must not be {@literal null}.
|
||||
* @param repositories must not be {@literal null}.
|
||||
*/
|
||||
private void persist(Object object, Repositories repositories) {
|
||||
CrudRepository<Object, Serializable> repository = repositories.getRepositoryFor(object.getClass());
|
||||
repository.save(object);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} to create a {@link ResourceReaderRepositoryPopulator} using an {@link Unmarshaller}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class UnmarshallerRepositoryPopulatorFactoryBean extends AbstractRepositoryPopulatorFactoryBean {
|
||||
|
||||
private Unmarshaller unmarshaller;
|
||||
|
||||
/**
|
||||
* Configures the {@link Unmarshaller} to be used.
|
||||
*
|
||||
* @param unmarshaller the unmarshaller to set
|
||||
*/
|
||||
public void setUnmarshaller(Unmarshaller unmarshaller) {
|
||||
this.unmarshaller = unmarshaller;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.init.AbstractRepositoryPopulatorFactoryBean#getResourceReader()
|
||||
*/
|
||||
@Override
|
||||
protected ResourceReader getResourceReader() {
|
||||
return new UnmarshallingResourceReader(unmarshaller);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(unmarshaller, "No Unmarshaller configured!");
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.oxm.Unmarshaller;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class UnmarshallingResourceReader implements ResourceReader {
|
||||
|
||||
private final Unmarshaller unmarshaller;
|
||||
|
||||
/**
|
||||
* @param unmarshaller
|
||||
*/
|
||||
public UnmarshallingResourceReader(Unmarshaller unmarshaller) {
|
||||
this.unmarshaller = unmarshaller;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.init.ResourceReader#readFrom(org.springframework.core.io.Resource, java.lang.ClassLoader)
|
||||
*/
|
||||
public Object readFrom(Resource resource, ClassLoader classLoader) throws IOException {
|
||||
StreamSource source = new StreamSource(resource.getInputStream());
|
||||
return unmarshaller.unmarshal(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/data/repository=org.springframework.data.repository.config.RepositoryNameSpaceHandler
|
||||
@@ -1,2 +1,3 @@
|
||||
http\://www.springframework.org/schema/data/repository/spring-repository-1.0.xsd=org/springframework/data/repository/config/spring-repository-1.0.xsd
|
||||
http\://www.springframework.org/schema/data/repository/spring-repository.xsd=org/springframework/data/repository/config/spring-repository-1.0.xsd
|
||||
http\://www.springframework.org/schema/data/repository/spring-repository-1.4.xsd=org/springframework/data/repository/config/spring-repository-1.4.xsd
|
||||
http\://www.springframework.org/schema/data/repository/spring-repository.xsd=org/springframework/data/repository/config/spring-repository-1.4.xsd
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Tooling related information for the repository namespace
|
||||
http\://www.springframework.org/schema/data/repository@name=Repository Namespace
|
||||
http\://www.springframework.org/schema/data/repository@prefix=repository
|
||||
http\://www.springframework.org/schema/data/repository@icon=org/springframework/jdbc/config/spring-jdbc.gif
|
||||
@@ -0,0 +1,202 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/data/repository"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
targetNamespace="http://www.springframework.org/schema/data/repository"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context"
|
||||
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
|
||||
|
||||
<xsd:complexType name="repositories">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="include-filter" type="context:filterType"
|
||||
minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Controls which eligible types to include for component scanning.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="exclude-filter" type="context:filterType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Controls which eligible types to exclude for component scanning.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="base-package" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the base package where the DAO interface will be tried to be detected.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="named-queries-location" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the location to look for a Properties file containing externally defined queries.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="repository">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Declares a single DAO instance.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports identifier="@id"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="custom-impl-ref" type="customImplementationReference"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="populator">
|
||||
<xsd:attribute name="location" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Where to find the files to read the objects from the repository shall be populated with.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<!-- XML (Unmarshaller) initializer -->
|
||||
|
||||
<xsd:element name="unmarshaller-populator">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="populator">
|
||||
<xsd:attribute name="unmarshaller-ref" type="unmarshallerRefType" use="required" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:simpleType name="unmarshallerRefType">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:expected-type type="org.springframework.oxm.Unmarshaller" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<!-- JSON (Jackson) initializer -->
|
||||
|
||||
<xsd:element name="jackson-populator">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="populator">
|
||||
<xsd:attribute name="object-mapper-ref" type="objectMapperType" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:simpleType name="objectMapperType">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:expected-type type="org.codehaus.jackson.map.ObjectMapper" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:attributeGroup name="repository-attributes">
|
||||
<xsd:attribute name="repository-impl-postfix" type="xsd:string"/>
|
||||
<xsd:attribute name="query-lookup-strategy" type="query-strategy"/>
|
||||
<xsd:attribute name="factory-class" type="classType"/>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:attributeGroup name="transactional-repository-attributes">
|
||||
<xsd:attributeGroup ref="repository-attributes"/>
|
||||
<xsd:attribute name="transaction-manager-ref" type="transactionManagerRef"/>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:simpleType name="query-strategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Determines the way query methods are being executed.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="create-if-not-found">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Tries to find a named query but creates a custom query if
|
||||
none can be found. (Default)
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="create">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Creates a query from the query method's name.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="use-declared-query">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Uses a declared query to execute. Fails if no
|
||||
declared query (either through named query or through @Query)
|
||||
is defined.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="customImplementationReference">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref"/>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="entityManagerFactoryRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.orm.jpa.AbstractEntityManagerFactoryBean"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="transactionManagerRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to type="org.springframework.transaction.PlatformTransactionManager"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="classType">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="direct">
|
||||
<tool:expected-type type="java.lang.Class"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.config;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.repository.init.JacksonResourceReader;
|
||||
import org.springframework.data.repository.init.ResourceReaderRepositoryPopulator;
|
||||
import org.springframework.data.repository.init.UnmarshallingResourceReader;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
* Integratin tests for the initializer namespace elements.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ResourceReaderRepositoryPopulatorBeanDefinitionParserIntegrationTests {
|
||||
|
||||
/**
|
||||
* @see DATACMNS-58
|
||||
*/
|
||||
@Test
|
||||
public void registersJacksonInitializerCorrectly() {
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("populators.xml", getClass()));
|
||||
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition("jackson-populator");
|
||||
assertThat(definition, is(notNullValue()));
|
||||
|
||||
Object bean = beanFactory.getBean("jackson-populator");
|
||||
assertThat(bean, is(instanceOf(ResourceReaderRepositoryPopulator.class)));
|
||||
Object resourceReader = ReflectionTestUtils.getField(bean, "reader");
|
||||
assertThat(resourceReader, is(instanceOf(JacksonResourceReader.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-58
|
||||
*/
|
||||
@Test
|
||||
public void registersXmlInitializerCorrectly() {
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("populators.xml", getClass()));
|
||||
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition("xml-populator");
|
||||
assertThat(definition, is(notNullValue()));
|
||||
|
||||
Object bean = beanFactory.getBean("xml-populator");
|
||||
assertThat(bean, is(instanceOf(ResourceReaderRepositoryPopulator.class)));
|
||||
Object resourceReader = ReflectionTestUtils.getField(bean, "reader");
|
||||
assertThat(resourceReader, is(instanceOf(UnmarshallingResourceReader.class)));
|
||||
Object unmarshaller = ReflectionTestUtils.getField(resourceReader, "unmarshaller");
|
||||
assertThat(unmarshaller, is(instanceOf(Jaxb2Marshaller.class)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class JacksonResourceReaderIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void readsFileWithMultipleObjects() throws Exception {
|
||||
|
||||
ResourceReader reader = new JacksonResourceReader();
|
||||
Object result = reader.readFrom(new ClassPathResource("data.json", getClass()), null);
|
||||
|
||||
assertThat(result, is(instanceOf(Collection.class)));
|
||||
assertThat((Collection<?>) result, hasSize(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class Person {
|
||||
|
||||
String firstname;
|
||||
String lastname;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.repository.init;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.support.Repositories;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link UnmarshallingRepositoryInitializer}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ResourceReaderRepositoryInitializerUnitTests {
|
||||
|
||||
@Mock
|
||||
ResourceReader reader;
|
||||
@Mock
|
||||
Repositories repositories;
|
||||
@Mock
|
||||
Resource resource;
|
||||
@Mock
|
||||
CrudRepository<Object, Serializable> repo;
|
||||
|
||||
@Test
|
||||
public void storesSingleObjectCorrectly() throws Exception {
|
||||
|
||||
Object reference = new Object();
|
||||
|
||||
setUpReferenceAndInititalize(reference);
|
||||
|
||||
verify(repo, times(1)).save(reference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void storesCollectionOfObjectsCorrectly() throws Exception {
|
||||
|
||||
Object object = new Object();
|
||||
Collection<Object> reference = Collections.singletonList(object);
|
||||
|
||||
setUpReferenceAndInititalize(reference);
|
||||
|
||||
verify(repo, times(1)).save(object);
|
||||
}
|
||||
|
||||
private void setUpReferenceAndInititalize(Object reference) throws Exception {
|
||||
|
||||
when(reader.readFrom(any(Resource.class), any(ClassLoader.class))).thenReturn(reference);
|
||||
when(repositories.getRepositoryFor(Object.class)).thenReturn(repo);
|
||||
|
||||
ResourceReaderRepositoryPopulator initializer = new ResourceReaderRepositoryPopulator(reader);
|
||||
initializer.setResources(resource);
|
||||
initializer.populate(repositories);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
xmlns:oxm="http://www.springframework.org/schema/oxm"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd
|
||||
http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<repository:jackson-populator id="jackson-populator"
|
||||
location="classpath:org/springframework/data/repository/init/data.json" />
|
||||
|
||||
<repository:unmarshaller-populator
|
||||
id="xml-populator" location="classpath:org/springframework/data/repository/init/data.xml"
|
||||
unmarshaller-ref="unmarshaller" />
|
||||
|
||||
<oxm:jaxb2-marshaller id="unmarshaller" contextPath="org.springframework.data.repository.config" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,3 @@
|
||||
[ { "_class" : "org.springframework.data.repository.init.Person",
|
||||
"firstname" : "Dave",
|
||||
"lastname" : "Matthews" } ]
|
||||
@@ -8,16 +8,19 @@ Import-Template:
|
||||
com.mysema.query.*;version="[2.2.0,3.0.0)";resolution:=optional,
|
||||
javax.enterprise.*;version="${cdi.version:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
javax.inject.*;version="[1.0.0,2.0.0)";resolution:=optional,
|
||||
javax.xml.transform.*;version="0";resolution:=optional,
|
||||
org.codehaus.jackson.*;version="${jackson.version:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.aop.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.beans.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}",
|
||||
org.springframework.core.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}",
|
||||
org.springframework.context.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.dao.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.util.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}",
|
||||
org.springframework.expression.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.expression.spel.standard.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.expression.spel.support.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.oxm.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.transaction.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.util.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}",
|
||||
org.springframework.validation.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.springframework.web.*;version="${org.springframework.version.30:[=.=.=,+1.0.0)}";resolution:=optional,
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
|
||||
@@ -1028,5 +1028,88 @@ public class UserController {
|
||||
</programlisting>
|
||||
</simplesect>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Repository populators</title>
|
||||
|
||||
<para>If you have been working with the JDBC module of Spring you're
|
||||
probably familiar with the support to populate a DataSource using SQL
|
||||
scripts. A similar abstraction is available on the repositories level
|
||||
although we don't use SQL as data definition language as we need to be
|
||||
store independent of course. Thus the populators support XML (through
|
||||
Spring's OXM abstraction) and JSON (through Jackson) to define data for
|
||||
the repositories to be populated with.</para>
|
||||
|
||||
<para>Assume you have a file <filename>data.json</filename> with the
|
||||
following content:</para>
|
||||
|
||||
<example>
|
||||
<title>Data defined in JSON</title>
|
||||
|
||||
<programlisting language="javascript">[ { "_class" : "com.acme.Person",
|
||||
"firstname" : "Dave",
|
||||
"lastname" : "Matthews" },
|
||||
{ "_class" : "com.acme.Person",
|
||||
"firstname" : "Carter",
|
||||
"lastname" : "Beauford" } ]</programlisting>
|
||||
</example>
|
||||
|
||||
<para>You can easily populate you repositories by using the populator
|
||||
elements of the repository namespace provided in Spring Data Commons. To
|
||||
get the just shown data be populated to your
|
||||
<interfacename>PersonRepository</interfacename> all you need to do is
|
||||
the following:</para>
|
||||
|
||||
<example>
|
||||
<title>Declaring a Jackson repository populator</title>
|
||||
|
||||
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/data/repository
|
||||
http://www.springframework.org/schema/data/repository/spring-repository.xsd">
|
||||
|
||||
<repository:jackson-populator location="classpath:data.json" />
|
||||
|
||||
</beans></programlisting>
|
||||
</example>
|
||||
|
||||
<para>This declaration causes the data.json file being read,
|
||||
deserialized by a Jackson <classname>ObjectMapper</classname>. The type
|
||||
the JSON object will be unmarshalled to will be determined by inspecting
|
||||
the <code>_class</code> attribute of the JSON document. We will
|
||||
eventually select the appropriate repository being able to handle the
|
||||
object just deserialized.</para>
|
||||
|
||||
<para>To rather use XML to define the repositories shall be populated
|
||||
with you can use the unmarshaller-populator you hand one of the
|
||||
marshaller options Spring OXM provides you with.</para>
|
||||
|
||||
<example>
|
||||
<title>Declaring an unmarshalling repository populator (using
|
||||
JAXB)</title>
|
||||
|
||||
<programlisting language="xml"><?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
xmlns:oxm="http://www.springframework.org/schema/oxm"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/data/repository
|
||||
http://www.springframework.org/schema/data/repository/spring-repository.xsd
|
||||
http://www.springframework.org/schema/oxm
|
||||
http://www.springframework.org/schema/oxm/spring-oxm.xsd">
|
||||
|
||||
<repository:unmarshaller-populator location="classpath:data.json" unmarshaller-ref="unmarshaller" />
|
||||
|
||||
<oxm:jaxb2-marshaller contextPath="com.acme" />
|
||||
|
||||
</beans></programlisting>
|
||||
</example>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user