Skip to content

Commit

Permalink
fixed #264
Browse files Browse the repository at this point in the history
  • Loading branch information
Mobe91 committed Oct 15, 2016
1 parent 19fb236 commit dca4f93
Show file tree
Hide file tree
Showing 22 changed files with 748 additions and 1 deletion.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,43 @@ Blaze-Persistence JPA-Criteria JPA 2.0 provider support dependencies
<scope>runtime</scope>
</dependency>
```
Spring Integration
------------------

```xml
<dependency>
<groupId>com.blazebit</groupId>
<artifactId>blaze-persistence-integration-entity-view-spring</artifactId>
<version>${blaze-persistence.version}</version>
</dependency>
```

You have to enable the Spring entity-views integration via annotation based config or XML based config and you can also mix those two types of configuration:

### Annotation Config

```java
@Configuration
@EnableEntityViews("my.entityviews.base.package")
public class AppConfig {
}
```

### XML Config

```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:ev="http://www.blazebit.com/persistence/view/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.blazebit.com/persistence/view/spring http://www.blazebit.com/persistence/view/spring/spring-entity-views-1.2.xsd">

<ev:entity-views base-package="my.entityviews.base.package"/>

</beans>
```

Documentation
=========
Expand Down Expand Up @@ -339,7 +376,7 @@ Questions or issues
===================

Drop by on [![Slack Status](https://blazebit.herokuapp.com/badge.svg)](https://blazebit.herokuapp.com) and ask questions any time or just create an issue on [GitHub](https://github.com/Blazebit/blaze-persistence/issues/new).

Licensing
=========

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.blazebit.persistence.view.testsuite.basic.model;

import com.blazebit.persistence.view.EntityView;
import com.blazebit.persistence.view.IdMapping;
import com.blazebit.persistence.view.Mapping;
import com.blazebit.persistence.view.testsuite.entity.Person;
import com.blazebit.persistence.view.testsuite.entity.Version;

import java.util.List;

/**
* Created
* by Moritz Becker ([email protected])
* on 01.10.2016.
*/
@EntityView(Person.class)
public interface PartnerDocumentVersionsView extends IdHolderView<Long> {

@Mapping("partnerDocument.versions")
List<Version> getOwnedDocuments();

@Mapping("partnerDocument.age")
Long getAge();

@Mapping("SIZE(ownedDocuments)")
Long getNumPartners();

DocumentViewInterface getPartnerDocument();

}
64 changes: 64 additions & 0 deletions integration/entity-view-spring/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>blaze-persistence-integration</artifactId>
<groupId>com.blazebit</groupId>
<version>1.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>blaze-persistence-integration-entity-view-spring</artifactId>
<packaging>jar</packaging>

<properties>
<version.spring>4.3.3.RELEASE</version.spring>
</properties>

<dependencies>
<dependency>
<groupId>com.blazebit</groupId>
<artifactId>blaze-persistence-entity-view-api</artifactId>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${version.spring}</version>
<scope>provided</scope>
</dependency>

<!-- Test Dependencies -->

<dependency>
<groupId>com.blazebit</groupId>
<artifactId>blaze-persistence-entity-view-impl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${version.spring}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.blazebit.persistence.view.impl.spring;

import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Created
* by Moritz Becker ([email protected])
* on 12.10.2016.
*/
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.TYPE})
@Documented
@Import({EntityViewRegistrar.class})
public @interface EnableEntityViews {
/**
* Alias for {@link #basePackages}.
* <p>Allows for more concise annotation declarations if no other attributes
* are needed &mdash; for example, {@code @ComponentScan("org.my.pkg")}
* instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
*/
@AliasFor("basePackages")
String[] value() default {};

/**
* Base packages to scan for annotated components.
* <p>{@link #value} is an alias for (and mutually exclusive with) this
* attribute.
* <p>Use {@link #basePackageClasses} for a type-safe alternative to
* String-based package names.
*/
@AliasFor("value")
String[] basePackages() default {};

/**
* Type-safe alternative to {@link #basePackages} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.blazebit.persistence.view.impl.spring;

import java.util.Set;

/**
* Created
* by Moritz Becker ([email protected])
* on 12.10.2016.
*/
public class EntityViewClassesHolder {

private final Set<Class<?>> entityViewClasses;

public EntityViewClassesHolder(Set<Class<?>> entityViewClasses) {
this.entityViewClasses = entityViewClasses;
}

public Set<Class<?>> getEntityViewClasses() {
return entityViewClasses;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.blazebit.persistence.view.impl.spring;

import com.blazebit.persistence.view.EntityViews;
import com.blazebit.persistence.view.spi.EntityViewConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

/**
* Created
* by Moritz Becker ([email protected])
* on 12.10.2016.
*/
@Configuration
public class EntityViewConfigurationProducer {

private final EntityViewConfiguration configuration = EntityViews.createDefaultConfiguration();

@Inject
private EntityViewClassesHolder entityViewClassesHolder;

@PostConstruct
public void initEntityViewConfiguration() throws ClassNotFoundException {
for (Class<?> entityViewClass : entityViewClassesHolder.getEntityViewClasses()) {
configuration.addEntityView(entityViewClass);
}
}

@Bean
public EntityViewConfiguration getEntityViewConfiguration() {
return configuration;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.blazebit.persistence.view.impl.spring;

import org.springframework.beans.factory.xml.NamespaceHandler;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

/**
* Created
* by Moritz Becker ([email protected])
* on 13.10.2016.
*/
public class EntityViewNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("entity-views", new EntityViewRegistrar());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.blazebit.persistence.view.impl.spring;

import com.blazebit.persistence.view.EntityView;
import com.blazebit.persistence.view.spi.EntityViewConfiguration;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.ReaderContext;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

import java.util.*;

/**
* Created
* by Moritz Becker ([email protected])
* on 12.10.2016.
*/
public class EntityViewRegistrar implements ImportBeanDefinitionRegistrar, BeanDefinitionParser {

private static final String BASE_PACKAGE = "base-package";

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
try {
BeanDefinitionRegistry registry = parserContext.getRegistry();

List<String> basePackages = getBasePackages(element);
if (basePackages.isEmpty()) {
parserContext.getReaderContext().error("You have to specify at least one base package for entity views!", element);
}

scanAndRegisterEntityViews(basePackages, registry);
} catch (RuntimeException e) {
handleError(e, element, parserContext.getReaderContext());
}

return null;
}

public List<String> getBasePackages(Element element) {
String attribute = element.getAttribute(BASE_PACKAGE);
return Arrays.asList(StringUtils.delimitedListToStringArray(attribute, ",", " "));
}

private void handleError(Exception e, Element source, ReaderContext reader) {
reader.error(e.getMessage(), reader.extractSource(source), e);
}

@Override
@SuppressWarnings("unchecked")
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
MultiValueMap<String, Object> annotationAttributes = importingClassMetadata.getAllAnnotationAttributes(EnableEntityViews.class.getName());

List<String> basePackages = new ArrayList<String>();
Collections.addAll(basePackages, (String[]) annotationAttributes.getFirst("value"));
Class<?>[] basePackageClasses = (Class<?>[]) annotationAttributes.getFirst("basePackageClasses");
for (Class<?> basePackageClass : basePackageClasses) {
basePackages.add(basePackageClass.getPackage().getName());
}
if (basePackages.isEmpty()) {
try {
basePackages.add(Class.forName(importingClassMetadata.getClassName()).getPackage().getName());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}

scanAndRegisterEntityViews(basePackages, registry);
}

@SuppressWarnings("unchecked")
private void scanAndRegisterEntityViews(List<String> basePackages, BeanDefinitionRegistry registry) {
Set<Class<?>> entityViewClasses = new HashSet<Class<?>>();
ClassPathScanningCandidateComponentProvider provider = createComponentScanner();
for (String basePackage : basePackages) {
for (BeanDefinition beanDef : provider.findCandidateComponents(basePackage)) {
try {
entityViewClasses.add(Class.forName(beanDef.getBeanClassName()));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

final String entityViewClassHolderBeanName = "entityViewClassesHolder";
if (registry.containsBeanDefinition(entityViewClassHolderBeanName)) {
BeanDefinition existingClassHolder = registry.getBeanDefinition(entityViewClassHolderBeanName);
Set<Class<?>> existingEntityViewClasses = (Set<Class<?>>) ((GenericBeanDefinition) existingClassHolder).getConstructorArgumentValues().getGenericArgumentValue(Set.class).getValue();
existingEntityViewClasses.addAll(entityViewClasses);
} else {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(EntityViewClassesHolder.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(entityViewClasses);
registry.registerBeanDefinition(entityViewClassHolderBeanName, beanDefinition);

// register configuration class
beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(EntityViewConfigurationProducer.class);
registry.registerBeanDefinition("entityViewConfigurationProducer", beanDefinition);
}
}

private ClassPathScanningCandidateComponentProvider createComponentScanner() {
ClassPathScanningCandidateComponentProvider provider
= new ClassPathScanningCandidateComponentProvider(false) {
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isIndependent();
}
};
provider.addIncludeFilter(new AnnotationTypeFilter(EntityView.class, false, true));
return provider;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
http\://www.blazebit.com/persistence/view/spring=com.blazebit.persistence.view.impl.spring.EntityViewNamespaceHandler
Loading

0 comments on commit dca4f93

Please sign in to comment.