Hibernate SVN: r16281 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/engine/xml and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-08 10:58:09 -0400 (Wed, 08 Apr 2009)
New Revision: 16281
Added:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/Optional.java
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
Log:
HV-112
GroupSequences
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08 13:21:22 UTC (rev 16280)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08 14:58:09 UTC (rev 16281)
@@ -136,6 +136,28 @@
return defaultGroupSequence;
}
+ public void setDefaultGroupSequence(List<Class<?>> groupSequence) {
+ defaultGroupSequence = new ArrayList<Class<?>>();
+ for ( Class<?> group : groupSequence ) {
+ if ( group.getName().equals( beanClass.getName() ) ) {
+ defaultGroupSequence.add( Default.class );
+ }
+ else if ( group.getName().equals( Default.class.getName() ) ) {
+ throw new ValidationException( "'Default.class' cannot appear in default group sequence list." );
+ }
+ else {
+ defaultGroupSequence.add( group );
+ }
+ }
+ if ( log.isDebugEnabled() ) {
+ log.debug(
+ "Bean {} redefines the Default group. Members of the default group sequence are: {}",
+ beanClass.getName(),
+ defaultGroupSequence
+ );
+ }
+ }
+
public Set<PropertyDescriptor> getConstrainedProperties() {
return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>( propertyDescriptors.values() ) );
}
@@ -148,7 +170,7 @@
*/
private void createMetaData(AnnotationIgnores annotationIgnores) {
beanDescriptor = new BeanDescriptorImpl<T>( this );
- initDefaultGroupSequence( beanClass );
+ initDefaultGroupSequence();
List<Class> classes = new ArrayList<Class>();
computeClassHierarchy( beanClass, classes );
for ( Class current : classes ) {
@@ -186,35 +208,17 @@
/**
* Checks whether there is a default group sequence defined for this class.
* See HV-113.
- *
- * @param clazz The class to check for the <code>GroupSequence</code> annotation.
*/
- private void initDefaultGroupSequence(Class<?> clazz) {
- GroupSequence groupSequenceAnnotation = clazz.getAnnotation( GroupSequence.class );
+ private void initDefaultGroupSequence() {
+ List<Class<?>> groupSequence = new ArrayList<Class<?>>();
+ GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class );
if ( groupSequenceAnnotation == null ) {
- defaultGroupSequence.add( Default.class );
+ groupSequence.add( beanClass );
}
else {
- List<Class<?>> groupSequenceList = Arrays.asList( groupSequenceAnnotation.value() );
- for ( Class<?> group : groupSequenceList ) {
- if ( group.getName().equals( clazz.getName() ) ) {
- defaultGroupSequence.add( Default.class );
- }
- else if ( group.getName().equals( Default.class.getName() ) ) {
- throw new ValidationException( "'Default.class' cannot appear in default group sequence list." );
- }
- else {
- defaultGroupSequence.add( group );
- }
- }
- if ( log.isDebugEnabled() ) {
- log.debug(
- "Bean {} redefines the Default group. Members of the default group sequence are: {}",
- clazz.getName(),
- defaultGroupSequence
- );
- }
+ groupSequence.addAll( Arrays.asList( groupSequenceAnnotation.value() ) );
}
+ setDefaultGroupSequence( groupSequence );
}
private <A extends Annotation> void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08 13:21:22 UTC (rev 16280)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08 14:58:09 UTC (rev 16281)
@@ -62,6 +62,7 @@
import org.hibernate.validation.xml.ElementType;
import org.hibernate.validation.xml.FieldType;
import org.hibernate.validation.xml.GetterType;
+import org.hibernate.validation.xml.GroupSequenceType;
import org.hibernate.validation.xml.GroupsType;
/**
@@ -81,9 +82,12 @@
private final ConstraintHelper constraintHelper = new ConstraintHelper();
private static final String PACKAGE_SEPERATOR = ".";
+ private final Set<Class<?>> processedClasses = new HashSet<Class<?>>();
+
private AnnotationIgnores annotationIgnores;
private Map<Class<?>, List<MetaConstraint<?, ?>>> constraintMap;
- private List<Member> cascadedMembers = new ArrayList<Member>();
+ private Map<Class<?>, List<Member>> cascadedMembers;
+ private Map<Class<?>, List<Class<?>>> defaultSequences;
public ValidatorFactoryImpl(ConfigurationState configurationState) {
this.messageInterpolator = configurationState.getMessageInterpolator();
@@ -92,6 +96,8 @@
annotationIgnores = new AnnotationIgnores();
constraintMap = new HashMap<Class<?>, List<MetaConstraint<?, ?>>>();
+ cascadedMembers = new HashMap<Class<?>, List<Member>>();
+ defaultSequences = new HashMap<Class<?>, List<Class<?>>>();
parseMappingFiles( configurationState.getMappingStreams() );
initBeanMetaData();
@@ -134,7 +140,6 @@
}
private void parseMappingFiles(Set<InputStream> mappingStreams) {
- Set<Class<?>> processedClasses = new HashSet<Class<?>>();
for ( InputStream in : mappingStreams ) {
try {
ConstraintMappingsType mappings = getValidationConfig( in );
@@ -182,7 +187,7 @@
// valid
if ( fieldType.getValid() != null ) {
- cascadedMembers.add( field );
+ addCascadedMember( beanClass, field );
}
// constraints
@@ -211,7 +216,7 @@
// valid
if ( getterType.getValid() != null ) {
- cascadedMembers.add( method );
+ addCascadedMember( beanClass, method );
}
// constraints
@@ -228,16 +233,35 @@
if ( classType == null ) {
return;
}
+
+ // ignore annotation
boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false : classType.isIgnoreAnnotations();
if ( ignoreClassAnnotation ) {
annotationIgnores.setIgnoreAnnotationsOnClass( beanClass );
}
+
+ // group sequence
+ List<Class<?>> groupSequence = createGroupSequence( classType.getGroupSequence(), beanClass, defaultPackage );
+ if ( !groupSequence.isEmpty() ) {
+ defaultSequences.put( beanClass, groupSequence );
+ }
+
+ // constraints
for ( ConstraintType constraint : classType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage );
addMetaConstraint( beanClass, metaConstraint );
}
}
+ private List<Class<?>> createGroupSequence(GroupSequenceType groupSequenceType, Class<?> beanClass, String defaultPackage) {
+ List<Class<?>> groupSequence = new ArrayList<Class<?>>();
+ for ( String groupName : groupSequenceType.getValue() ) {
+ Class<?> group = getClass( groupName, defaultPackage );
+ groupSequence.add( group );
+ }
+ return groupSequence;
+ }
+
private void addMetaConstraint(Class<?> beanClass, MetaConstraint<?, ?> metaConstraint) {
if ( constraintMap.containsKey( beanClass ) ) {
constraintMap.get( beanClass ).add( metaConstraint );
@@ -249,6 +273,17 @@
}
}
+ private void addCascadedMember(Class<?> beanClass, Member member) {
+ if ( cascadedMembers.containsKey( beanClass ) ) {
+ cascadedMembers.get( beanClass ).add( member );
+ }
+ else {
+ List<Member> tmpList = new ArrayList<Member>();
+ tmpList.add( member );
+ cascadedMembers.put( beanClass, tmpList );
+ }
+ }
+
private <A extends Annotation, T> MetaConstraint<?, ?> createMetaConstraint(ConstraintType constraint, Class<T> beanClass, Member member, String defaultPackage) {
@SuppressWarnings("unchecked")
Class<A> annotationClass = ( Class<A> ) getClass( constraint.getAnnotation(), defaultPackage );
@@ -473,15 +508,19 @@
}
private void initBeanMetaData() {
- for ( Map.Entry<Class<?>, List<MetaConstraint<?, ?>>> entry : constraintMap.entrySet() ) {
- BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( entry.getKey(), constraintHelper, annotationIgnores );
- for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
- metaData.addMetaConstraint( metaConstraint );
+
+ for ( Class<?> beanClass : processedClasses ) {
+ BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( beanClass, constraintHelper, annotationIgnores );
+ for ( MetaConstraint<?, ?> constraint : constraintMap.get( beanClass ) ) {
+ metaData.addMetaConstraint( constraint );
}
- for ( Member m : cascadedMembers ) {
+ for ( Member m : cascadedMembers.get( beanClass ) ) {
metaData.addCascadedMember( m );
}
- BeanMetaDataCache.addBeanMetaData( entry.getKey(), metaData );
+ if ( defaultSequences.containsKey( beanClass ) ) {
+ metaData.setDefaultGroupSequence( defaultSequences.get( beanClass ) );
+ }
+ BeanMetaDataCache.addBeanMetaData( beanClass, metaData );
}
}
}
Copied: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/Optional.java (from rev 16271, validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/TestGroup.java)
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/Optional.java (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/Optional.java 2009-04-08 14:58:09 UTC (rev 16281)
@@ -0,0 +1,24 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.hibernate.validation.engine.xml;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public interface Optional {
+}
\ No newline at end of file
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08 13:21:22 UTC (rev 16280)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08 14:58:09 UTC (rev 16281)
@@ -17,7 +17,7 @@
private CreditCard creditcard;
- @Pattern(regexp = "[0-9 -]+", message = "A phone number can only contain numbers, whitespaces and dashes.")
+ @Pattern(regexp = "[0-9 -]+", message = "A phone number can only contain numbers, whitespaces and dashes.", groups = Optional.class)
private String phoneNumber;
@NotNull(groups = Default.class)
Modified: validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08 13:21:22 UTC (rev 16280)
+++ validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08 14:58:09 UTC (rev 16281)
@@ -5,7 +5,8 @@
<bean class="User" ignore-annotations="false">
<class ignore-annotations="true">
<group-sequence>
- <value>value0</value>
+ <value>User</value>
+ <value>Optional</value>
</group-sequence>
<constraint annotation="org.hibernate.validation.engine.xml.ConsistentUserInformation">
<message>Message from xml</message>
15 years, 7 months
Hibernate SVN: r16280 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/engine/xml and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-08 09:21:22 -0400 (Wed, 08 Apr 2009)
New Revision: 16280
Added:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/CreditCard.java
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
Log:
HV-112
Support for cascaded fields/properties in xml
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08 12:48:10 UTC (rev 16279)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08 13:21:22 UTC (rev 16280)
@@ -124,6 +124,10 @@
metaConstraintList.add( ( MetaConstraint<T, ?> ) metaConstraint );
}
+ public void addCascadedMember(Member member) {
+ cascadedMembers.add( member );
+ }
+
public PropertyDescriptor getPropertyDescriptor(String property) {
return propertyDescriptors.get( property );
}
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08 12:48:10 UTC (rev 16279)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08 13:21:22 UTC (rev 16280)
@@ -83,6 +83,7 @@
private AnnotationIgnores annotationIgnores;
private Map<Class<?>, List<MetaConstraint<?, ?>>> constraintMap;
+ private List<Member> cascadedMembers = new ArrayList<Member>();
public ValidatorFactoryImpl(ConfigurationState configurationState) {
this.messageInterpolator = configurationState.getMessageInterpolator();
@@ -172,10 +173,19 @@
throw new ValidationException( beanClass.getName() + " does not contain the fieldType " + fieldName );
}
Field field = ReflectionHelper.getField( beanClass, fieldName );
+
+ // ignore annotations
boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false : fieldType.isIgnoreAnnotations();
if ( ignoreFieldAnnotation ) {
annotationIgnores.setIgnoreAnnotationsOnMember( field );
}
+
+ // valid
+ if ( fieldType.getValid() != null ) {
+ cascadedMembers.add( field );
+ }
+
+ // constraints
for ( ConstraintType constraint : fieldType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
constraint, beanClass, field, defaultPackage
@@ -186,17 +196,26 @@
}
private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?> beanClass, String defaultPackage) {
- for ( GetterType getter : getters ) {
- String getterName = getter.getName();
+ for ( GetterType getterType : getters ) {
+ String getterName = getterType.getName();
if ( !ReflectionHelper.containsMethod( beanClass, getterName ) ) {
throw new ValidationException( beanClass.getName() + " does not contain the property " + getterName );
}
Method method = ReflectionHelper.getMethod( beanClass, getterName );
- boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false : getter.isIgnoreAnnotations();
+
+ // ignore annotations
+ boolean ignoreGetterAnnotation = getterType.isIgnoreAnnotations() == null ? false : getterType.isIgnoreAnnotations();
if ( ignoreGetterAnnotation ) {
annotationIgnores.setIgnoreAnnotationsOnMember( method );
}
- for ( ConstraintType constraint : getter.getConstraint() ) {
+
+ // valid
+ if ( getterType.getValid() != null ) {
+ cascadedMembers.add( method );
+ }
+
+ // constraints
+ for ( ConstraintType constraint : getterType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
constraint, beanClass, method, defaultPackage
);
@@ -459,6 +478,9 @@
for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
metaData.addMetaConstraint( metaConstraint );
}
+ for ( Member m : cascadedMembers ) {
+ metaData.addCascadedMember( m );
+ }
BeanMetaDataCache.addBeanMetaData( entry.getKey(), metaData );
}
}
Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/CreditCard.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/CreditCard.java (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/CreditCard.java 2009-04-08 13:21:22 UTC (rev 16280)
@@ -0,0 +1,37 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.hibernate.validation.engine.xml;
+
+import javax.validation.constraints.Pattern;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class CreditCard {
+
+ @Pattern(regexp = "[0-9]+", message = "Not a credit casrd number.")
+ private String number;
+
+ public String getNumber() {
+ return number;
+ }
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+}
Property changes on: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/CreditCard.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08 12:48:10 UTC (rev 16279)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08 13:21:22 UTC (rev 16280)
@@ -15,7 +15,9 @@
private String lastname;
- @Pattern(regexp = "[0-9 -]+", message = "A phone nmber can only contain numbers, whitespaces and dashes.")
+ private CreditCard creditcard;
+
+ @Pattern(regexp = "[0-9 -]+", message = "A phone number can only contain numbers, whitespaces and dashes.")
private String phoneNumber;
@NotNull(groups = Default.class)
@@ -50,4 +52,12 @@
public boolean isConsistent() {
return isConsistent;
}
+
+ public CreditCard getCreditcard() {
+ return creditcard;
+ }
+
+ public void setCreditcard(CreditCard creditcard) {
+ this.creditcard = creditcard;
+ }
}
\ No newline at end of file
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-08 12:48:10 UTC (rev 16279)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-08 13:21:22 UTC (rev 16280)
@@ -95,11 +95,33 @@
assertNumberOfViolations( constraintViolations, 1 );
TestUtil.assertConstraintViolation(
constraintViolations.iterator().next(),
- "A phone nmber can only contain numbers, whitespaces and dashes."
+ "A phone number can only contain numbers, whitespaces and dashes."
);
user.setPhoneNumber( "112" );
constraintViolations = validator.validate( user );
assertNumberOfViolations( constraintViolations, 0 );
}
+
+ @Test
+ public void testCascadingConfiguredInXml() {
+ Validator validator = getValidator();
+
+ User user = new User();
+ user.setConsistent( true );
+ CreditCard card = new CreditCard();
+ card.setNumber( "not a number" );
+ user.setCreditcard( card );
+
+ Set<ConstraintViolation<User>> constraintViolations = validator.validate( user );
+ assertNumberOfViolations( constraintViolations, 1 );
+ TestUtil.assertConstraintViolation(
+ constraintViolations.iterator().next(),
+ "Not a credit casrd number."
+ );
+
+ card.setNumber( "1234567890" );
+ constraintViolations = validator.validate( user );
+ assertNumberOfViolations( constraintViolations, 0 );
+ }
}
Modified: validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08 12:48:10 UTC (rev 16279)
+++ validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08 13:21:22 UTC (rev 16280)
@@ -39,8 +39,10 @@
</element-->
</constraint>
</field>
+ <field name="creditcard">
+ <valid/>
+ </field>
<getter name="firstname" ignore-annotations="true">
- <valid/>
<constraint annotation="javax.validation.constraints.Size">
<message>Size is limited!</message>
<groups>
15 years, 7 months
Hibernate SVN: r16279 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/constraints and 2 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-08 08:48:10 -0400 (Wed, 08 Apr 2009)
New Revision: 16279
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
Log:
HV-112
Added a new class for taking care of the annotation ignores.
Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java 2009-04-08 12:48:10 UTC (rev 16279)
@@ -0,0 +1,119 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.hibernate.validation.engine;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+
+/**
+ * This class instantiated during the parsing of the XML configuration data and keeps
+ * track of the annotations which should be ignored.
+ *
+ * @author Hardy Ferentschik
+ */
+public class AnnotationIgnores {
+
+ private static final Logger log = LoggerFactory.make();
+
+ /**
+ * Keeps track whether the 'ignore-annotations' flag is set on bean level in the xml configuration. If 'ignore-annotations'
+ * is not specified <code>false</code> is the default.
+ */
+ private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new HashMap<Class<?>, Boolean>();
+
+ /**
+ * Keeps track of explicitly excluded members (fields and properties) for a given class. If a member appears in
+ * the list mapped to a given class 'ignore-annotations' was explicitly set to <code>true</code> in the configuration
+ * for this class.
+ */
+ private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember = new HashMap<Class<?>, List<Member>>();
+
+ private final List<Class<?>> ignoreAnnotationOnClass = new ArrayList<Class<?>>();
+
+ public void setDefaultIgnoreAnnotation(Class<?> clazz, Boolean b) {
+ if ( b == null ) {
+ ignoreAnnotationDefaults.put( clazz, Boolean.FALSE );
+ }
+ else {
+ ignoreAnnotationDefaults.put( clazz, b );
+ }
+ }
+
+ public boolean getDefaultIgnoreAnnotation(Class<?> clazz) {
+ return ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz );
+ }
+
+ public void setIgnoreAnnotationsOnMember(Member member) {
+ Class<?> beanClass = member.getDeclaringClass();
+ if ( ignoreAnnotationOnMember.get( beanClass ) == null ) {
+ List<Member> tmpList = new ArrayList<Member>();
+ tmpList.add( member );
+ ignoreAnnotationOnMember.put( beanClass, tmpList );
+ }
+ else {
+ ignoreAnnotationOnMember.get( beanClass ).add( member );
+ }
+ }
+
+ public boolean isIgnoreAnnotations(Member member) {
+ boolean ignoreAnnotation;
+ Class<?> clazz = member.getDeclaringClass();
+ List<Member> ignoreAnnotationForMembers = ignoreAnnotationOnMember.get( clazz );
+ if ( ignoreAnnotationForMembers == null || !ignoreAnnotationForMembers.contains( member ) ) {
+ ignoreAnnotation = getDefaultIgnoreAnnotation( clazz );
+ }
+ else {
+ ignoreAnnotation = ignoreAnnotationForMembers.contains( member );
+ }
+ if ( ignoreAnnotation ) {
+ logMessage( member, clazz );
+ }
+ return ignoreAnnotation;
+ }
+
+ private void logMessage(Member member, Class<?> clazz) {
+ String type;
+ if ( member instanceof Field ) {
+ type = "Field";
+ }
+ else {
+ type = "Property";
+ }
+ log.debug( type + " level annotations are getting ignored for " + clazz.getName() + "." + member.getName() );
+ }
+
+ public void setIgnoreAnnotationsOnClass(Class<?> clazz) {
+ ignoreAnnotationOnClass.add( clazz );
+ }
+
+ public boolean isIgnoreAnnotations(Class<?> clazz) {
+ boolean ignoreAnnotation = ignoreAnnotationOnClass.contains( clazz ) || getDefaultIgnoreAnnotation( clazz );
+ if ( log.isDebugEnabled() && ignoreAnnotation ) {
+ log.debug( "Class level annotation are getting ignored for " + clazz.getName() );
+ }
+ return ignoreAnnotation;
+ }
+}
Property changes on: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/AnnotationIgnores.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08 11:23:35 UTC (rev 16278)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-08 12:48:10 UTC (rev 16279)
@@ -90,32 +90,18 @@
*/
private final ConstraintHelper constraintHelper;
- private Map<Class<?>, Boolean> ignoreAnnotationDefaults;
- private Map<Class<?>, List<Member>> ignoreAnnotationOnMember;
- private List<Class<?>> ignoreAnnotationOnClass;
-
public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
this(
beanClass,
constraintHelper,
- new HashMap<Class<?>, Boolean>(),
- new ArrayList<Class<?>>(),
- new HashMap<Class<?>, List<Member>>()
+ new AnnotationIgnores()
);
}
- public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper, Map<Class<?>, Boolean> ignoreAnnotationDefaults, List<Class<?>> ignoreAnnotationOnClass, Map<Class<?>, List<Member>> ignoreAnnotationOnMember) {
+ public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper, AnnotationIgnores annotationIgnores) {
this.beanClass = beanClass;
this.constraintHelper = constraintHelper;
- this.ignoreAnnotationDefaults = ignoreAnnotationDefaults;
- this.ignoreAnnotationOnClass = ignoreAnnotationOnClass;
- this.ignoreAnnotationOnMember = ignoreAnnotationOnMember;
-
- createMetaData();
-
- this.ignoreAnnotationDefaults = null;
- this.ignoreAnnotationOnClass = null;
- this.ignoreAnnotationOnMember = null;
+ createMetaData( annotationIgnores );
}
public Class<T> getBeanClass() {
@@ -153,14 +139,16 @@
/**
* Create bean desciptor, find all classes/subclasses/interfaces which have to be taken in consideration
* for this validator and create meta data.
+ *
+ * @param annotationIgnores Datastructure keeping track on which annotation should be ignored.
*/
- private void createMetaData() {
+ private void createMetaData(AnnotationIgnores annotationIgnores) {
beanDescriptor = new BeanDescriptorImpl<T>( this );
initDefaultGroupSequence( beanClass );
List<Class> classes = new ArrayList<Class>();
computeClassHierarchy( beanClass, classes );
for ( Class current : classes ) {
- initClass( current );
+ initClass( current, annotationIgnores );
}
}
@@ -185,10 +173,10 @@
}
}
- private void initClass(Class clazz) {
- initClassConstraints( clazz );
- initMethodConstraints( clazz );
- initFieldConstraints( clazz );
+ private void initClass(Class clazz, AnnotationIgnores annotationIgnores) {
+ initClassConstraints( clazz, annotationIgnores );
+ initMethodConstraints( clazz, annotationIgnores );
+ initFieldConstraints( clazz, annotationIgnores );
}
/**
@@ -225,11 +213,11 @@
}
}
- private <A extends Annotation> void initFieldConstraints(Class clazz) {
+ private <A extends Annotation> void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
for ( Field field : clazz.getDeclaredFields() ) {
List<ConstraintDescriptorImpl> fieldMetadata = findConstraints( field );
for ( ConstraintDescriptorImpl constraintDescription : fieldMetadata ) {
- if ( checkSkipAnnotationProcessing( clazz, field ) ) {
+ if ( annotationIgnores.isIgnoreAnnotations( field ) ) {
break;
}
ReflectionHelper.setAccessibility( field );
@@ -246,11 +234,11 @@
}
}
- private <A extends Annotation> void initMethodConstraints(Class clazz) {
+ private <A extends Annotation> void initMethodConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
for ( Method method : clazz.getDeclaredMethods() ) {
List<ConstraintDescriptorImpl> methodMetadata = findConstraints( method );
for ( ConstraintDescriptorImpl constraintDescription : methodMetadata ) {
- if ( checkSkipAnnotationProcessing( clazz, method ) ) {
+ if ( annotationIgnores.isIgnoreAnnotations( method ) ) {
break;
}
ReflectionHelper.setAccessibility( method );
@@ -267,29 +255,6 @@
}
}
- private boolean checkSkipAnnotationProcessing(Class clazz, Member member) {
- List<Member> ignoreAnnotationForFields = ignoreAnnotationOnMember.get( clazz );
- boolean ignoreAnnotation;
- if ( ignoreAnnotationForFields == null || !ignoreAnnotationForFields.contains( member ) ) {
- ignoreAnnotation = ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz );
- }
- else {
- ignoreAnnotation = ignoreAnnotationForFields.contains( member );
- }
- if ( ignoreAnnotation ) {
- String type;
- if ( member instanceof Field ) {
- type = "Field";
- }
- else {
- type = "Property";
- }
- log.debug( type + " level annotations are getting ignored for " + clazz.getName() + "." + member.getName() );
- return true;
- }
- return false;
- }
-
private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
String name = ReflectionHelper.getPropertyName( member );
PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get(
@@ -306,10 +271,8 @@
return propertyDescriptor;
}
- private <A extends Annotation> void initClassConstraints(Class clazz) {
- if ( ignoreAnnotationOnClass.contains( clazz ) ||
- ( ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz ) ) ) {
- log.debug( "Class level annotation are getting ignored for " + clazz.getName() );
+ private <A extends Annotation> void initClassConstraints(Class clazz, AnnotationIgnores annotationIgnores) {
+ if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) {
return;
}
List<ConstraintDescriptorImpl> classMetadata = findClassLevelConstraints( clazz );
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08 11:23:35 UTC (rev 16278)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-08 12:48:10 UTC (rev 16279)
@@ -81,16 +81,17 @@
private final ConstraintHelper constraintHelper = new ConstraintHelper();
private static final String PACKAGE_SEPERATOR = ".";
- private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new HashMap<Class<?>, Boolean>();
- private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember = new HashMap<Class<?>, List<Member>>();
- private final List<Class<?>> ignoreAnnotationOnClass = new ArrayList<Class<?>>();
- private final Map<Class<?>, List<MetaConstraint<?, ?>>> constraintMap = new HashMap<Class<?>, List<MetaConstraint<?, ?>>>();
+ private AnnotationIgnores annotationIgnores;
+ private Map<Class<?>, List<MetaConstraint<?, ?>>> constraintMap;
public ValidatorFactoryImpl(ConfigurationState configurationState) {
this.messageInterpolator = configurationState.getMessageInterpolator();
this.constraintValidatorFactory = configurationState.getConstraintValidatorFactory();
this.traversableResolver = configurationState.getTraversableResolver();
+ annotationIgnores = new AnnotationIgnores();
+ constraintMap = new HashMap<Class<?>, List<MetaConstraint<?, ?>>>();
+
parseMappingFiles( configurationState.getMappingStreams() );
initBeanMetaData();
}
@@ -140,8 +141,7 @@
for ( BeanType bean : mappings.getBean() ) {
Class<?> beanClass = getClass( bean.getClazz(), defaultPackage );
checkClassHasNotBeenProcessed( processedClasses, beanClass );
- Boolean ignoreAnnotations = bean.isIgnoreAnnotations() == null ? false : bean.isIgnoreAnnotations();
- ignoreAnnotationDefaults.put( beanClass, ignoreAnnotations );
+ annotationIgnores.setDefaultIgnoreAnnotation( beanClass, bean.isIgnoreAnnotations() );
parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
parseFieldLevelOverrides( bean.getField(), beanClass, defaultPackage );
parsePropertyLevelOverrides( bean.getGetter(), beanClass, defaultPackage );
@@ -174,7 +174,7 @@
Field field = ReflectionHelper.getField( beanClass, fieldName );
boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false : fieldType.isIgnoreAnnotations();
if ( ignoreFieldAnnotation ) {
- addMemberToIgnoreList( beanClass, field );
+ annotationIgnores.setIgnoreAnnotationsOnMember( field );
}
for ( ConstraintType constraint : fieldType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
@@ -185,17 +185,6 @@
}
}
- private void addMemberToIgnoreList(Class<?> beanClass, Member member) {
- if ( ignoreAnnotationOnMember.get( beanClass ) == null ) {
- List<Member> ignoredAnnotationOnMember = new ArrayList<Member>();
- ignoredAnnotationOnMember.add( member );
- ignoreAnnotationOnMember.put( beanClass, ignoredAnnotationOnMember );
- }
- else {
- ignoreAnnotationOnMember.get( beanClass ).add( member );
- }
- }
-
private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?> beanClass, String defaultPackage) {
for ( GetterType getter : getters ) {
String getterName = getter.getName();
@@ -205,7 +194,7 @@
Method method = ReflectionHelper.getMethod( beanClass, getterName );
boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false : getter.isIgnoreAnnotations();
if ( ignoreGetterAnnotation ) {
- addMemberToIgnoreList( beanClass, method );
+ annotationIgnores.setIgnoreAnnotationsOnMember( method );
}
for ( ConstraintType constraint : getter.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
@@ -222,7 +211,7 @@
}
boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false : classType.isIgnoreAnnotations();
if ( ignoreClassAnnotation ) {
- ignoreAnnotationOnClass.add( beanClass );
+ annotationIgnores.setIgnoreAnnotationsOnClass( beanClass );
}
for ( ConstraintType constraint : classType.getConstraint() ) {
MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage );
@@ -466,13 +455,7 @@
private void initBeanMetaData() {
for ( Map.Entry<Class<?>, List<MetaConstraint<?, ?>>> entry : constraintMap.entrySet() ) {
- BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl(
- entry.getKey(),
- constraintHelper,
- ignoreAnnotationDefaults,
- ignoreAnnotationOnClass,
- ignoreAnnotationOnMember
- );
+ BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( entry.getKey(), constraintHelper, annotationIgnores );
for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
metaData.addMetaConstraint( metaConstraint );
}
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java 2009-04-08 11:23:35 UTC (rev 16278)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternValidatorTest.java 2009-04-08 12:48:10 UTC (rev 16279)
@@ -42,7 +42,6 @@
PatternValidator constraint = new PatternValidator();
constraint.initialize( p );
-
assertTrue( constraint.isValid( null, null ) );
assertFalse( constraint.isValid( "", null ) );
assertFalse( constraint.isValid( "bla bla", null ) );
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08 11:23:35 UTC (rev 16278)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-08 12:48:10 UTC (rev 16279)
@@ -1,6 +1,7 @@
package org.hibernate.validation.engine.xml;
import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
import javax.validation.groups.Default;
/**
@@ -14,7 +15,7 @@
private String lastname;
- //@Pattern(regexp = "[0-9 -]?", groups = Optional.class)
+ @Pattern(regexp = "[0-9 -]+", message = "A phone nmber can only contain numbers, whitespaces and dashes.")
private String phoneNumber;
@NotNull(groups = Default.class)
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-08 11:23:35 UTC (rev 16278)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-08 12:48:10 UTC (rev 16279)
@@ -82,4 +82,24 @@
constraintViolations = validator.validate( user );
assertNumberOfViolations( constraintViolations, 0 );
}
+
+ @Test
+ public void testAnnotationDefinedConstraintApplies() {
+ Validator validator = getValidator();
+
+ User user = new User();
+ user.setConsistent( true );
+ user.setPhoneNumber( "police" );
+
+ Set<ConstraintViolation<User>> constraintViolations = validator.validate( user );
+ assertNumberOfViolations( constraintViolations, 1 );
+ TestUtil.assertConstraintViolation(
+ constraintViolations.iterator().next(),
+ "A phone nmber can only contain numbers, whitespaces and dashes."
+ );
+
+ user.setPhoneNumber( "112" );
+ constraintViolations = validator.validate( user );
+ assertNumberOfViolations( constraintViolations, 0 );
+ }
}
Modified: validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08 11:23:35 UTC (rev 16278)
+++ validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-08 12:48:10 UTC (rev 16279)
@@ -25,7 +25,7 @@
<field name="lastname">
<constraint annotation="javax.validation.constraints.Pattern">
<message>Last name has to start with with a capital letter.</message>
- <element name="regexp">^[A-Z].*</element>
+ <element name="regexp">^[A-Z][a-z]+</element>
<!--element name="patterns">
<annotation>
<element name="value">myRegExp</element>
15 years, 7 months
Hibernate SVN: r16278 - search/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-08 07:23:35 -0400 (Wed, 08 Apr 2009)
New Revision: 16278
Modified:
search/trunk/pom.xml
Log:
Added 'test' as default goal
Modified: search/trunk/pom.xml
===================================================================
--- search/trunk/pom.xml 2009-04-08 10:20:10 UTC (rev 16277)
+++ search/trunk/pom.xml 2009-04-08 11:23:35 UTC (rev 16278)
@@ -115,6 +115,7 @@
</dependencies>
<build>
+ <defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
15 years, 7 months
Hibernate SVN: r16277 - in search/trunk/src: main/java/org/hibernate/search/backend/impl and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: sannegrinovero
Date: 2009-04-08 06:20:10 -0400 (Wed, 08 Apr 2009)
New Revision: 16277
Added:
search/trunk/src/main/java/org/hibernate/search/event/IndexWorkFlushEventListener.java
search/trunk/src/test/java/org/hibernate/search/test/engine/
search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java
search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java
search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java
search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java
Removed:
search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java
search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java
search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java
search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java
Modified:
search/trunk/src/main/docbook/en-US/modules/configuration.xml
search/trunk/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java
search/trunk/src/main/java/org/hibernate/search/backend/impl/TransactionalWorker.java
search/trunk/src/main/java/org/hibernate/search/event/EventListenerRegister.java
search/trunk/src/test/java/org/hibernate/search/test/TestCase.java
search/trunk/src/test/java/org/hibernate/search/test/classloading/NoAnnotationsTest.java
Log:
HSEARCH-178 for trunk
Modified: search/trunk/src/main/docbook/en-US/modules/configuration.xml
===================================================================
--- search/trunk/src/main/docbook/en-US/modules/configuration.xml 2009-04-08 09:39:36 UTC (rev 16276)
+++ search/trunk/src/main/docbook/en-US/modules/configuration.xml 2009-04-08 10:20:10 UTC (rev 16277)
@@ -605,7 +605,8 @@
<para>To enable Hibernate Search in Hibernate Core (ie. if you don't use
Hibernate Annotations), add the
<literal>FullTextIndexEventListener</literal> for the following six
- Hibernate events.</para>
+ Hibernate events and add the <literal>IndexWorkFlushEventListener</literal> after
+ the default <literal>DefaultFlushEventListener</literal>, as in the following example.</para>
<example>
<title>Explicitly enabling Hibernate Search by configuring the
@@ -614,24 +615,28 @@
<programlisting><hibernate-configuration>
<session-factory>
...
- <event type="post-update"/>
+ <event type="post-update">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-insert"/>
+ <event type="post-insert">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-delete"/>
+ <event type="post-delete">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-collection-recreate"/>
+ <event type="post-collection-recreate">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-collection-remove"/>
+ <event type="post-collection-remove">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-collection-update"/>
+ <event type="post-collection-update">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
+ <event type="flush">
+ <listener class="org.hibernate.event.def.DefaultFlushEventListener"/>
+ <listener class="org.hibernate.search.event.IndexWorkFlushEventListener"/>
+ </event>
</session-factory>
</hibernate-configuration></programlisting>
</example>
Modified: search/trunk/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java 2009-04-08 09:39:36 UTC (rev 16276)
+++ search/trunk/src/main/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -2,35 +2,93 @@
package org.hibernate.search.backend.impl;
import java.io.Serializable;
+
import javax.transaction.Synchronization;
+import org.hibernate.AssertionFailure;
import org.hibernate.Transaction;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.FlushEventListener;
import org.hibernate.search.backend.TransactionContext;
-import org.hibernate.event.EventSource;
+import org.hibernate.search.event.IndexWorkFlushEventListener;
+import org.hibernate.search.util.LoggerFactory;
+import org.slf4j.Logger;
/**
* Implementation of the transactional context on top of an EventSource (Session)
*
* @author Navin Surtani - navin(a)surtani.org
+ * @author Emmanuel Bernard
+ * @author Sanne Grinovero
*/
public class EventSourceTransactionContext implements TransactionContext, Serializable {
- EventSource eventSource;
+
+ private static final Logger log = LoggerFactory.make();
+
+ private final EventSource eventSource;
+ private final IndexWorkFlushEventListener flushListener;
+ //constructor time is too early to define the value of realTxInProgress,
+ //postpone it, otherwise doing
+ // " openSession - beginTransaction "
+ //will behave as "out of transaction" in the whole session lifespan.
+ private Boolean realTxInProgress = null;
+
public EventSourceTransactionContext(EventSource eventSource) {
this.eventSource = eventSource;
+ this.flushListener = findIndexWorkFlushEventListener();
}
public Object getTransactionIdentifier() {
- return eventSource.getTransaction();
+ if ( isRealTransactionInProgress() ) {
+ return eventSource.getTransaction();
+ }
+ else {
+ return eventSource;
+ }
}
public void registerSynchronization(Synchronization synchronization) {
- Transaction transaction = eventSource.getTransaction();
- transaction.registerSynchronization( synchronization );
+ if ( isRealTransactionInProgress() ) {
+ Transaction transaction = eventSource.getTransaction();
+ transaction.registerSynchronization( synchronization );
+ }
+ else {
+ if ( flushListener != null ) {
+ flushListener.addSynchronization( eventSource, synchronization );
+ }
+ else {
+ //It appears we are flushing out of transaction and have no way to perform the index update
+ //Not expected: see check in isTransactionInProgress()
+ throw new AssertionFailure( "On flush out of transaction: IndexWorkFlushEventListener not registered" );
+ }
+ }
}
+
+ private IndexWorkFlushEventListener findIndexWorkFlushEventListener() {
+ FlushEventListener[] flushEventListeners = eventSource.getListeners().getFlushEventListeners();
+ for (FlushEventListener listener : flushEventListeners) {
+ if ( listener.getClass().equals( IndexWorkFlushEventListener.class ) ) {
+ return (IndexWorkFlushEventListener) listener;
+ }
+ }
+ log.debug( "No IndexWorkFlushEventListener was registered" );
+ return null;
+ }
+ //The code is not really fitting the method name;
+ //(unless you consider a flush as a mini-transaction)
+ //This is because we want to behave as "inTransaction" if the flushListener is registered.
public boolean isTransactionInProgress() {
- return eventSource.isTransactionInProgress();
+ // either it is a real transaction, or if we are capable to manage this in the IndexWorkFlushEventListener
+ return isRealTransactionInProgress() || flushListener != null;
}
-
+
+ private boolean isRealTransactionInProgress() {
+ if ( realTxInProgress == null ) {
+ realTxInProgress = eventSource.isTransactionInProgress();
+ }
+ return realTxInProgress;
+ }
+
}
Modified: search/trunk/src/main/java/org/hibernate/search/backend/impl/TransactionalWorker.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/backend/impl/TransactionalWorker.java 2009-04-08 09:39:36 UTC (rev 16276)
+++ search/trunk/src/main/java/org/hibernate/search/backend/impl/TransactionalWorker.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -1,71 +1,83 @@
-//$Id$
-package org.hibernate.search.backend.impl;
-
-import java.util.Properties;
-
-import javax.transaction.Synchronization;
-
-import org.hibernate.search.backend.QueueingProcessor;
-import org.hibernate.search.backend.Work;
-import org.hibernate.search.backend.WorkQueue;
-import org.hibernate.search.backend.Worker;
-import org.hibernate.search.backend.TransactionContext;
-import org.hibernate.search.engine.SearchFactoryImplementor;
-import org.hibernate.search.util.WeakIdentityHashMap;
-
-/**
- * Queue works per transaction.
- * If out of transaction, the work is executed right away
- * <p/>
- * When <code>hibernate.search.worker.type</code> is set to <code>async</code>
- * the work is done in a separate thread (threads are pooled)
- *
- * @author Emmanuel Bernard
- */
-public class TransactionalWorker implements Worker {
- //not a synchronized map since for a given transaction, we have not concurrent access
- protected final WeakIdentityHashMap<Object, Synchronization> synchronizationPerTransaction = new WeakIdentityHashMap<Object, Synchronization>();
- private QueueingProcessor queueingProcessor;
-
- public void performWork(Work work, TransactionContext transactionContext) {
- if ( transactionContext.isTransactionInProgress() ) {
- Object transaction = transactionContext.getTransactionIdentifier();
- PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
- synchronizationPerTransaction.get( transaction );
- if ( txSync == null || txSync.isConsumed() ) {
- txSync = new PostTransactionWorkQueueSynchronization(
- queueingProcessor, synchronizationPerTransaction
- );
- transactionContext.registerSynchronization( txSync );
- synchronizationPerTransaction.put( transaction, txSync );
- }
- txSync.add( work );
- }
- else {
- WorkQueue queue = new WorkQueue( 2 ); //one work can be split
- queueingProcessor.add( work, queue );
- queueingProcessor.prepareWorks( queue );
- queueingProcessor.performWorks( queue );
- }
- }
-
- public void initialize(Properties props, SearchFactoryImplementor searchFactory) {
- this.queueingProcessor = new BatchedQueueingProcessor( searchFactory, props );
- }
-
- public void close() {
- queueingProcessor.close();
- }
-
- public void flushWorks(TransactionContext transactionContext) {
- if ( transactionContext.isTransactionInProgress() ) {
- Object transaction = transactionContext.getTransactionIdentifier();
- PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
- synchronizationPerTransaction.get( transaction );
- if ( txSync != null && !txSync.isConsumed() ) {
- txSync.flushWorks();
- }
- }
- }
-
-}
+//$Id$
+package org.hibernate.search.backend.impl;
+
+import java.util.Properties;
+
+import javax.transaction.Synchronization;
+
+import org.hibernate.search.backend.QueueingProcessor;
+import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.WorkQueue;
+import org.hibernate.search.backend.Worker;
+import org.hibernate.search.backend.TransactionContext;
+import org.hibernate.search.engine.SearchFactoryImplementor;
+import org.hibernate.search.util.LoggerFactory;
+import org.hibernate.search.util.WeakIdentityHashMap;
+import org.slf4j.Logger;
+
+/**
+ * Queue works per transaction.
+ * If out of transaction, the work is executed right away
+ * <p/>
+ * When <code>hibernate.search.worker.type</code> is set to <code>async</code>
+ * the work is done in a separate thread (threads are pooled)
+ *
+ * @author Emmanuel Bernard
+ */
+public class TransactionalWorker implements Worker {
+
+ //note: there is one Worker instance per SearchFactory, reused concurrently for all sessions.
+
+ private static final Logger log = LoggerFactory.make();
+
+ //FIXME: discuss the next line! it looks like there actually is concurrent access
+ //not a synchronized map since for a given transaction, we have not concurrent access
+ protected final WeakIdentityHashMap<Object, Synchronization> synchronizationPerTransaction = new WeakIdentityHashMap<Object, Synchronization>();
+ private QueueingProcessor queueingProcessor;
+
+ public void performWork(Work work, TransactionContext transactionContext) {
+ if ( transactionContext.isTransactionInProgress() ) {
+ Object transactionIdentifier = transactionContext.getTransactionIdentifier();
+ PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
+ synchronizationPerTransaction.get( transactionIdentifier );
+ if ( txSync == null || txSync.isConsumed() ) {
+ txSync = new PostTransactionWorkQueueSynchronization(
+ queueingProcessor, synchronizationPerTransaction
+ );
+ transactionContext.registerSynchronization( txSync );
+ synchronizationPerTransaction.put( transactionIdentifier, txSync );
+ }
+ txSync.add( work );
+ }
+ else {
+ // this is a workaround: isTransactionInProgress should return "true"
+ // for correct configurations.
+ log.warn( "It appears changes are being pushed to the index out of a transaction. " +
+ "Register the IndexWorkFlushEventListener listener on flush to correctly manage Collections!" );
+ WorkQueue queue = new WorkQueue( 2 ); //one work can be split
+ queueingProcessor.add( work, queue );
+ queueingProcessor.prepareWorks( queue );
+ queueingProcessor.performWorks( queue );
+ }
+ }
+
+ public void initialize(Properties props, SearchFactoryImplementor searchFactory) {
+ this.queueingProcessor = new BatchedQueueingProcessor( searchFactory, props );
+ }
+
+ public void close() {
+ queueingProcessor.close();
+ }
+
+ public void flushWorks(TransactionContext transactionContext) {
+ if ( transactionContext.isTransactionInProgress() ) {
+ Object transaction = transactionContext.getTransactionIdentifier();
+ PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
+ synchronizationPerTransaction.get( transaction );
+ if ( txSync != null && !txSync.isConsumed() ) {
+ txSync.flushWorks();
+ }
+ }
+ }
+
+}
Modified: search/trunk/src/main/java/org/hibernate/search/event/EventListenerRegister.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/event/EventListenerRegister.java 2009-04-08 09:39:36 UTC (rev 16276)
+++ search/trunk/src/main/java/org/hibernate/search/event/EventListenerRegister.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -94,7 +94,13 @@
new PostCollectionUpdateEventListener[] { searchListener }
)
);
-
+ // Adding IndexWorkFlushEventListener to manage events out-of-transaction
+ if ( ! isFlushEventListenerRegistered( listeners.getFlushEventListeners() ) ) {
+ listeners.setFlushEventListeners( appendToArray(
+ listeners.getFlushEventListeners(),
+ new IndexWorkFlushEventListener()
+ ) );
+ }
}
/**
@@ -159,4 +165,19 @@
}
return false;
}
+
+ /**
+ * Verifies if an IndexWorkFlushEventListener is contained in the array of listeners.
+ * @param listeners
+ * @return true if it found in the listeners, false otherwise.
+ */
+ private static boolean isFlushEventListenerRegistered(Object[] listeners) {
+ for ( Object eventListener : listeners ) {
+ if ( IndexWorkFlushEventListener.class == eventListener.getClass() ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
Copied: search/trunk/src/main/java/org/hibernate/search/event/IndexWorkFlushEventListener.java (from rev 16272, search/branches/Branch_3_1/src/java/org/hibernate/search/event/IndexWorkFlushEventListener.java)
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/event/IndexWorkFlushEventListener.java (rev 0)
+++ search/trunk/src/main/java/org/hibernate/search/event/IndexWorkFlushEventListener.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -0,0 +1,61 @@
+// $Id$
+package org.hibernate.search.event;
+
+import java.io.Serializable;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+
+import org.hibernate.AssertionFailure;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.FlushEvent;
+import org.hibernate.event.FlushEventListener;
+import org.hibernate.search.util.LoggerFactory;
+import org.slf4j.Logger;
+
+/**
+ * FlushEventListener to make sure the indexes are updated right after the hibernate flush,
+ * avoiding object loading during a flush. Not needed during transactions.
+ *
+ * @author Sanne Grinovero
+ */
+public final class IndexWorkFlushEventListener implements FlushEventListener, Serializable {
+
+ private static final Logger log = LoggerFactory.make();
+
+ private final ConcurrentHashMap<Session, Synchronization> synchronizationPerTransaction
+ = new ConcurrentHashMap<Session, Synchronization>();
+
+ public IndexWorkFlushEventListener() {
+ }
+
+ public void onFlush(FlushEvent event) throws HibernateException {
+ Session session = event.getSession();
+ Synchronization synchronization = synchronizationPerTransaction.get( session );
+ if ( synchronization != null ) {
+ log.debug( "flush event causing index update out of transaction" );
+ synchronizationPerTransaction.remove( session );
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion( Status.STATUS_COMMITTED );
+ }
+ }
+
+ public void addSynchronization(EventSource eventSource, Synchronization synchronization) {
+ Synchronization previousSync = synchronizationPerTransaction.put( eventSource, synchronization );
+ if ( previousSync != null ) {
+ throw new AssertionFailure( "previous registered sync not discarded in IndexWorkFlushEventListener" );
+ }
+ }
+
+ /*
+ * Might want to implement AutoFlushEventListener in future?
+ public void onAutoFlush(AutoFlushEvent event) throws HibernateException {
+ // Currently not needed as auto-flush is not happening
+ // when out of transaction.
+ }
+ */
+
+}
Modified: search/trunk/src/test/java/org/hibernate/search/test/TestCase.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/TestCase.java 2009-04-08 09:39:36 UTC (rev 16276)
+++ search/trunk/src/test/java/org/hibernate/search/test/TestCase.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -13,6 +13,9 @@
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
+import org.hibernate.event.FlushEventListener;
+import org.hibernate.event.def.DefaultFlushEventListener;
+import org.hibernate.search.event.IndexWorkFlushEventListener;
/**
* A modified base class for tests without annotations.
@@ -143,9 +146,15 @@
}
protected void configure(Configuration cfg) {
+ //needs to register all event listeners:
cfg.setListener( "post-update", "org.hibernate.search.event.FullTextIndexEventListener" );
cfg.setListener( "post-insert", "org.hibernate.search.event.FullTextIndexEventListener" );
cfg.setListener( "post-delete", "org.hibernate.search.event.FullTextIndexEventListener" );
+ cfg.setListener( "post-collection-recreate", "org.hibernate.search.event.FullTextIndexEventListener" );
+ cfg.setListener( "post-collection-remove", "org.hibernate.search.event.FullTextIndexEventListener" );
+ cfg.setListener( "post-collection-update", "org.hibernate.search.event.FullTextIndexEventListener" );
+
+ cfg.setListeners( "flush", new FlushEventListener[]{new DefaultFlushEventListener(), new IndexWorkFlushEventListener()} );
cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
cfg.setProperty( org.hibernate.search.Environment.ANALYZER_CLASS, StopAnalyzer.class.getName() );
Modified: search/trunk/src/test/java/org/hibernate/search/test/classloading/NoAnnotationsTest.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/classloading/NoAnnotationsTest.java 2009-04-08 09:39:36 UTC (rev 16276)
+++ search/trunk/src/test/java/org/hibernate/search/test/classloading/NoAnnotationsTest.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -10,7 +10,6 @@
import org.hibernate.Transaction;
import org.hibernate.search.Search;
-
/**
* @author Hardy Ferentschik
*/
@@ -39,7 +38,28 @@
tx.commit();
s.close();
}
+
+ public void testFlushListenerRegistrationWithoutAnnotations() throws Exception {
+ // This test should pass even if the flushListener is not registered,
+ // as a workaround is done in code (you'll see a warning in logs).
+ Animal pinguin = new Animal();
+ pinguin.setName( "Penguin" );
+ Session s = openSession();
+ s.save( pinguin );
+ s.flush();
+ s.clear();
+
+ Transaction tx = s.beginTransaction();
+ tx = s.beginTransaction();
+ List results = Search.getFullTextSession( s ).createFullTextQuery(
+ new TermQuery( new Term( "name", "penguin" ) )
+ ).list();
+ assertEquals( 1, results.size() );
+ tx.commit();
+ s.close();
+ }
+
protected String[] getXmlFiles() {
return new String[] {
"org/hibernate/search/test/classloading/Animal.hbm.xml"
Copied: search/trunk/src/test/java/org/hibernate/search/test/engine (from rev 16272, search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine)
Deleted: search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusLine.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -1,87 +0,0 @@
-// $Id$
-package org.hibernate.search.test.engine;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.ManyToMany;
-
-import org.hibernate.search.annotations.Field;
-import org.hibernate.search.annotations.Index;
-import org.hibernate.search.annotations.Indexed;
-import org.hibernate.search.annotations.IndexedEmbedded;
-import org.hibernate.search.annotations.Store;
-
-/**
- * Test entity: BusLine have many BusStops: needed to verify
- * indexing of a lazy-loaded collection in out-of-transaction use case.
- *
- * @author Sanne Grinovero
- */
-@Entity
-@Indexed
-public class BusLine {
-
- private Long id;
- private String busLineName;
- private Set<BusStop> stops = new HashSet<BusStop>();
-
- @Id
- @GeneratedValue
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- @Field(index=Index.NO,store=Store.YES)
- public String getBusLineName() {
- return busLineName;
- }
-
- public void setBusLineName(String busLine) {
- this.busLineName = busLine;
- }
-
- @ManyToMany(cascade=CascadeType.PERSIST)
- @IndexedEmbedded
- public Set<BusStop> getStops() {
- return stops;
- }
-
- public void setStops(Set<BusStop> stops) {
- this.stops = stops;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((busLineName == null) ? 0 : busLineName.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- BusLine other = (BusLine) obj;
- if (busLineName == null) {
- if (other.busLineName != null)
- return false;
- } else if (!busLineName.equals(other.busLineName))
- return false;
- return true;
- }
-
-}
Copied: search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java (from rev 16272, search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusLine.java)
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -0,0 +1,87 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.IndexedEmbedded;
+import org.hibernate.search.annotations.Store;
+
+/**
+ * Test entity: BusLine have many BusStops: needed to verify
+ * indexing of a lazy-loaded collection in out-of-transaction use case.
+ *
+ * @author Sanne Grinovero
+ */
+@Entity
+@Indexed
+public class BusLine {
+
+ private Long id;
+ private String busLineName;
+ private Set<BusStop> stops = new HashSet<BusStop>();
+
+ @Id
+ @GeneratedValue
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Field(index=Index.NO,store=Store.YES)
+ public String getBusLineName() {
+ return busLineName;
+ }
+
+ public void setBusLineName(String busLine) {
+ this.busLineName = busLine;
+ }
+
+ @ManyToMany(cascade=CascadeType.PERSIST)
+ @IndexedEmbedded
+ public Set<BusStop> getStops() {
+ return stops;
+ }
+
+ public void setStops(Set<BusStop> stops) {
+ this.stops = stops;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((busLineName == null) ? 0 : busLineName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BusLine other = (BusLine) obj;
+ if (busLineName == null) {
+ if (other.busLineName != null)
+ return false;
+ } else if (!busLineName.equals(other.busLineName))
+ return false;
+ return true;
+ }
+
+}
Property changes on: search/trunk/src/test/java/org/hibernate/search/test/engine/BusLine.java
___________________________________________________________________
Name: svn:keywords
+ Id
Deleted: search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -1,82 +0,0 @@
-// $Id$
-package org.hibernate.search.test.engine;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Id;
-import javax.persistence.ManyToMany;
-
-import org.hibernate.search.annotations.ContainedIn;
-import org.hibernate.search.annotations.Field;
-
-/**
- * Test entity: BusStop is @ContainedIn BusLine
- *
- * @author Sanne Grinovero
- */
-@Entity
-public class BusStop {
-
- private Long id;
- private String roadName;
- private Set<BusLine> busses = new HashSet<BusLine>();
-
- @Id
- @GeneratedValue
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- @Field
- public String getRoadName() {
- return roadName;
- }
-
- public void setRoadName(String roadName) {
- this.roadName = roadName;
- }
-
- @ManyToMany(mappedBy="stops")
- @ContainedIn
- public Set<BusLine> getBusses() {
- return busses;
- }
-
- public void setBusses(Set<BusLine> busses) {
- this.busses = busses;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result
- + ((roadName == null) ? 0 : roadName.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- BusStop other = (BusStop) obj;
- if (roadName == null) {
- if (other.roadName != null)
- return false;
- } else if (!roadName.equals(other.roadName))
- return false;
- return true;
- }
-
-}
Copied: search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java (from rev 16272, search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java)
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/BusStop.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -0,0 +1,82 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.Field;
+
+/**
+ * Test entity: BusStop is @ContainedIn BusLine
+ *
+ * @author Sanne Grinovero
+ */
+@Entity
+public class BusStop {
+
+ private Long id;
+ private String roadName;
+ private Set<BusLine> busses = new HashSet<BusLine>();
+
+ @Id
+ @GeneratedValue
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Field
+ public String getRoadName() {
+ return roadName;
+ }
+
+ public void setRoadName(String roadName) {
+ this.roadName = roadName;
+ }
+
+ @ManyToMany(mappedBy="stops")
+ @ContainedIn
+ public Set<BusLine> getBusses() {
+ return busses;
+ }
+
+ public void setBusses(Set<BusLine> busses) {
+ this.busses = busses;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((roadName == null) ? 0 : roadName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BusStop other = (BusStop) obj;
+ if (roadName == null) {
+ if (other.roadName != null)
+ return false;
+ } else if (!roadName.equals(other.roadName))
+ return false;
+ return true;
+ }
+
+}
Deleted: search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -1,119 +0,0 @@
-// $Id$
-package org.hibernate.search.test.engine;
-
-import java.util.List;
-
-import org.apache.lucene.analysis.SimpleAnalyzer;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.TermQuery;
-import org.hibernate.Transaction;
-import org.hibernate.search.Environment;
-import org.hibernate.search.FullTextQuery;
-import org.hibernate.search.FullTextSession;
-import org.hibernate.search.Search;
-import org.hibernate.search.store.RAMDirectoryProvider;
-import org.hibernate.search.test.SearchTestCase;
-
-/**
- * TestCase for HSEARCH-178 (Search hitting HHH-2763)
- * Verifies that it's possible to index lazy loaded collections from
- * indexed entities even when no transactions are used.
- *
- * @author Sanne Grinovero
- */
-public class LazyCollectionsUpdatingTest extends SearchTestCase {
-
- public void testUpdatingInTransaction() {
- assertFindsByRoadName( "buonarroti" );
- FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
- try {
- Transaction tx = fullTextSession.beginTransaction();
- BusStop busStop = (BusStop) fullTextSession.get( BusStop.class, 1L );
- busStop.setRoadName( "new road" );
- tx.commit();
- }
- catch (org.hibernate.AssertionFailure ass) {
- fail( ass.getMessage() );
- }
- finally {
- fullTextSession.close();
- }
- assertFindsByRoadName( "new" );
- }
-
- public void testUpdatingOutOfTransaction() {
- assertFindsByRoadName( "buonarroti" );
- FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
- try {
- BusStop busStop = (BusStop) fullTextSession.get( BusStop.class, 1L );
- busStop.setRoadName( "new road" );
- fullTextSession.flush();
- }
- catch (org.hibernate.AssertionFailure ass) {
- fail( ass.getMessage() );
- }
- finally {
- fullTextSession.close();
- }
- assertFindsByRoadName( "new" );
- }
-
- public void assertFindsByRoadName(String analyzedRoadname) {
- FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
- Transaction tx = fullTextSession.beginTransaction();
- TermQuery ftQuery = new TermQuery( new Term( "stops.roadName", analyzedRoadname ) );
- FullTextQuery query = fullTextSession.createFullTextQuery( ftQuery, BusLine.class );
- query.setProjection( "busLineName" );
- assertEquals( 1, query.list().size() );
- List results = query.list();
- String resultName = (String) ((Object[])results.get(0))[0];
- assertEquals( "Linea 64", resultName );
- tx.commit();
- fullTextSession.close();
- }
-
- @Override
- public void setUp() throws Exception {
- super.setUp();
- openSession();
- Transaction tx = null;
- try {
- tx = session.beginTransaction();
- BusLine bus = new BusLine();
- bus.setBusLineName( "Linea 64" );
- addBusStop( bus, "Stazione Termini" );
- addBusStop( bus, "via Gregorio VII" );
- addBusStop( bus, "via Alessandro III" );
- addBusStop( bus, "via M.Buonarroti" );
- session.persist( bus );
- tx.commit();
- } catch (Throwable t) {
- if ( tx != null )
- tx.rollback();
- } finally {
- session.close();
- }
- }
-
- private void addBusStop(BusLine bus, String roadName) {
- BusStop stop = new BusStop();
- stop.setRoadName( roadName );
- bus.getStops().add( stop );
- stop.getBusses().add( bus );
- }
-
- // Test setup options - Entities
- @Override
- protected Class[] getMappings() {
- return new Class[] { BusLine.class, BusStop.class };
- }
-
- // Test setup options - SessionFactory Properties
- @Override
- protected void configure(org.hibernate.cfg.Configuration configuration) {
- super.configure( configuration );
- cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
- cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
- }
-
-}
Copied: search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java (from rev 16272, search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java)
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -0,0 +1,119 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import java.util.List;
+
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.TermQuery;
+import org.hibernate.Transaction;
+import org.hibernate.search.Environment;
+import org.hibernate.search.FullTextQuery;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.store.RAMDirectoryProvider;
+import org.hibernate.search.test.SearchTestCase;
+
+/**
+ * TestCase for HSEARCH-178 (Search hitting HHH-2763)
+ * Verifies that it's possible to index lazy loaded collections from
+ * indexed entities even when no transactions are used.
+ *
+ * @author Sanne Grinovero
+ */
+public class LazyCollectionsUpdatingTest extends SearchTestCase {
+
+ public void testUpdatingInTransaction() {
+ assertFindsByRoadName( "buonarroti" );
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ try {
+ Transaction tx = fullTextSession.beginTransaction();
+ BusStop busStop = (BusStop) fullTextSession.get( BusStop.class, 1L );
+ busStop.setRoadName( "new road" );
+ tx.commit();
+ }
+ catch (org.hibernate.AssertionFailure ass) {
+ fail( ass.getMessage() );
+ }
+ finally {
+ fullTextSession.close();
+ }
+ assertFindsByRoadName( "new" );
+ }
+
+ public void testUpdatingOutOfTransaction() {
+ assertFindsByRoadName( "buonarroti" );
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ try {
+ BusStop busStop = (BusStop) fullTextSession.get( BusStop.class, 1L );
+ busStop.setRoadName( "new road" );
+ fullTextSession.flush();
+ }
+ catch (org.hibernate.AssertionFailure ass) {
+ fail( ass.getMessage() );
+ }
+ finally {
+ fullTextSession.close();
+ }
+ assertFindsByRoadName( "new" );
+ }
+
+ public void assertFindsByRoadName(String analyzedRoadname) {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ TermQuery ftQuery = new TermQuery( new Term( "stops.roadName", analyzedRoadname ) );
+ FullTextQuery query = fullTextSession.createFullTextQuery( ftQuery, BusLine.class );
+ query.setProjection( "busLineName" );
+ assertEquals( 1, query.list().size() );
+ List results = query.list();
+ String resultName = (String) ((Object[])results.get(0))[0];
+ assertEquals( "Linea 64", resultName );
+ tx.commit();
+ fullTextSession.close();
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ BusLine bus = new BusLine();
+ bus.setBusLineName( "Linea 64" );
+ addBusStop( bus, "Stazione Termini" );
+ addBusStop( bus, "via Gregorio VII" );
+ addBusStop( bus, "via Alessandro III" );
+ addBusStop( bus, "via M.Buonarroti" );
+ session.persist( bus );
+ tx.commit();
+ } catch (Throwable t) {
+ if ( tx != null )
+ tx.rollback();
+ } finally {
+ session.close();
+ }
+ }
+
+ private void addBusStop(BusLine bus, String roadName) {
+ BusStop stop = new BusStop();
+ stop.setRoadName( roadName );
+ bus.getStops().add( stop );
+ stop.getBusses().add( bus );
+ }
+
+ // Test setup options - Entities
+ @Override
+ protected Class[] getMappings() {
+ return new Class[] { BusLine.class, BusStop.class };
+ }
+
+ // Test setup options - SessionFactory Properties
+ @Override
+ protected void configure(org.hibernate.cfg.Configuration configuration) {
+ super.configure( configuration );
+ cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
+ cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
+ }
+
+}
Deleted: search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -1,90 +0,0 @@
-// $Id$
-package org.hibernate.search.test.engine;
-
-import org.apache.lucene.analysis.SimpleAnalyzer;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.hibernate.Transaction;
-import org.hibernate.search.Environment;
-import org.hibernate.search.FullTextQuery;
-import org.hibernate.search.FullTextSession;
-import org.hibernate.search.Search;
-import org.hibernate.search.store.RAMDirectoryProvider;
-import org.hibernate.search.test.SearchTestCase;
-
-/**
- * Verify index changes queued during a transaction are canceled
- * when the transaction is rolled back.
- *
- * @author Sanne Grinovero
- */
-public class RollbackTransactionTest extends SearchTestCase {
-
- public void testTransactionBehaviour() {
- assertEquals( 0, countBusLinesByFullText() );
- assertEquals( 0, countBusLineByDatabaseCount() );
- createBusLines( 5, true );
- assertEquals( 0, countBusLinesByFullText() );
- assertEquals( 0, countBusLineByDatabaseCount() );
- createBusLines( 5, false );
- assertEquals( 5, countBusLinesByFullText() );
- assertEquals( 5, countBusLineByDatabaseCount() );
- createBusLines( 7, true );
- assertEquals( 5, countBusLinesByFullText() );
- assertEquals( 5, countBusLineByDatabaseCount() );
- createBusLines( 7, false );
- assertEquals( 12, countBusLinesByFullText() );
- assertEquals( 12, countBusLineByDatabaseCount() );
- }
-
- private void createBusLines(int number, boolean rollback) {
- FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
- Transaction tx = fullTextSession.beginTransaction();
- for (int i=0; i<number; i++ ) {
- BusLine line = new BusLine();
- line.setBusLineName( "line " + i );
- fullTextSession.persist( line );
- }
- if ( rollback ) {
- tx.rollback();
- }
- else {
- tx.commit();
- }
- fullTextSession.close();
- }
-
- public int countBusLinesByFullText() {
- FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
- Transaction tx = fullTextSession.beginTransaction();
- org.apache.lucene.search.Query ftQuery = new MatchAllDocsQuery();
- FullTextQuery query = fullTextSession.createFullTextQuery( ftQuery, BusLine.class );
- int count = query.list().size();
- tx.commit();
- fullTextSession.close();
- return count;
- }
-
- public int countBusLineByDatabaseCount() {
- FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
- Transaction tx = fullTextSession.beginTransaction();
- int count = fullTextSession.createCriteria( BusLine.class ).list().size();
- tx.commit();
- fullTextSession.close();
- return count;
- }
-
- // Test setup options - Entities
- @Override
- protected Class[] getMappings() {
- return new Class[] { BusLine.class, BusStop.class };
- }
-
- // Test setup options - SessionFactory Properties
- @Override
- protected void configure(org.hibernate.cfg.Configuration configuration) {
- super.configure( configuration );
- cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
- cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
- }
-
-}
Copied: search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java (from rev 16272, search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java)
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java (rev 0)
+++ search/trunk/src/test/java/org/hibernate/search/test/engine/RollbackTransactionTest.java 2009-04-08 10:20:10 UTC (rev 16277)
@@ -0,0 +1,90 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.hibernate.Transaction;
+import org.hibernate.search.Environment;
+import org.hibernate.search.FullTextQuery;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.store.RAMDirectoryProvider;
+import org.hibernate.search.test.SearchTestCase;
+
+/**
+ * Verify index changes queued during a transaction are canceled
+ * when the transaction is rolled back.
+ *
+ * @author Sanne Grinovero
+ */
+public class RollbackTransactionTest extends SearchTestCase {
+
+ public void testTransactionBehaviour() {
+ assertEquals( 0, countBusLinesByFullText() );
+ assertEquals( 0, countBusLineByDatabaseCount() );
+ createBusLines( 5, true );
+ assertEquals( 0, countBusLinesByFullText() );
+ assertEquals( 0, countBusLineByDatabaseCount() );
+ createBusLines( 5, false );
+ assertEquals( 5, countBusLinesByFullText() );
+ assertEquals( 5, countBusLineByDatabaseCount() );
+ createBusLines( 7, true );
+ assertEquals( 5, countBusLinesByFullText() );
+ assertEquals( 5, countBusLineByDatabaseCount() );
+ createBusLines( 7, false );
+ assertEquals( 12, countBusLinesByFullText() );
+ assertEquals( 12, countBusLineByDatabaseCount() );
+ }
+
+ private void createBusLines(int number, boolean rollback) {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ for (int i=0; i<number; i++ ) {
+ BusLine line = new BusLine();
+ line.setBusLineName( "line " + i );
+ fullTextSession.persist( line );
+ }
+ if ( rollback ) {
+ tx.rollback();
+ }
+ else {
+ tx.commit();
+ }
+ fullTextSession.close();
+ }
+
+ public int countBusLinesByFullText() {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ org.apache.lucene.search.Query ftQuery = new MatchAllDocsQuery();
+ FullTextQuery query = fullTextSession.createFullTextQuery( ftQuery, BusLine.class );
+ int count = query.list().size();
+ tx.commit();
+ fullTextSession.close();
+ return count;
+ }
+
+ public int countBusLineByDatabaseCount() {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ int count = fullTextSession.createCriteria( BusLine.class ).list().size();
+ tx.commit();
+ fullTextSession.close();
+ return count;
+ }
+
+ // Test setup options - Entities
+ @Override
+ protected Class[] getMappings() {
+ return new Class[] { BusLine.class, BusStop.class };
+ }
+
+ // Test setup options - SessionFactory Properties
+ @Override
+ protected void configure(org.hibernate.cfg.Configuration configuration) {
+ super.configure( configuration );
+ cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
+ cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
+ }
+
+}
15 years, 7 months
Hibernate SVN: r16276 - search/branches/Branch_3_1.
by hibernate-commits@lists.jboss.org
Author: sannegrinovero
Date: 2009-04-08 05:39:36 -0400 (Wed, 08 Apr 2009)
New Revision: 16276
Modified:
search/branches/Branch_3_1/ivy.xml
Log:
HSEARCH-348 (upgrading to Lucene 2.4.1)
Modified: search/branches/Branch_3_1/ivy.xml
===================================================================
--- search/branches/Branch_3_1/ivy.xml 2009-04-07 22:13:05 UTC (rev 16275)
+++ search/branches/Branch_3_1/ivy.xml 2009-04-08 09:39:36 UTC (rev 16276)
@@ -19,7 +19,7 @@
<dependency org="org.slf4j" name="slf4j-api" rev="1.4.2" conf="default->default"/>
<dependency org="org.hibernate" name="hibernate-core" rev="3.3.1.GA" conf="default->default"/>
<dependency org="javax.transaction" name="jta" rev="1.1" conf="default->default"/>
- <dependency org="org.apache.lucene" name="lucene-core" rev="2.4.0" conf="default->default"/>
+ <dependency org="org.apache.lucene" name="lucene-core" rev="2.4.1" conf="default->default"/>
<dependency org="javax.jms" name="jms" rev="1.1" conf="default->default"/> <!-- optional -->
<dependency org="javax.annotation" name="jsr250-api" rev="1.0" conf="default->default"/> <!-- optional -->
<dependency org="org.apache.solr" name="solr-core" rev="1.3.0" conf="default->default"/> <!-- optional -->
@@ -33,8 +33,8 @@
<!-- test deps -->
<dependency name="annotations" rev="3.4.0.GA" conf="test->default"/>
<dependency name="entitymanager" rev="3.4.0.GA" conf="test->default"/>
- <dependency org="org.apache.lucene" name="lucene-snowball" rev="2.4.0" conf="test->default"/>
- <dependency org="org.apache.lucene" name="lucene-analyzers" rev="2.4.0" conf="test->default"/>
+ <dependency org="org.apache.lucene" name="lucene-snowball" rev="2.4.1" conf="test->default"/>
+ <dependency org="org.apache.lucene" name="lucene-analyzers" rev="2.4.1" conf="test->default"/>
<dependency org="org.apache.commons" name="commons-codec" rev="1.3" conf="test->default"/>
<dependency org="org.apache.commons" name="commons-io" rev="1.3.2" conf="test->default"/>
<dependency org="cglib" name="cglib" rev="2.1_3" conf="test->default"/>
15 years, 7 months
Hibernate SVN: r16275 - search/branches/Branch_3_1/src/java/org/hibernate/search/engine.
by hibernate-commits@lists.jboss.org
Author: sannegrinovero
Date: 2009-04-07 18:13:05 -0400 (Tue, 07 Apr 2009)
New Revision: 16275
Modified:
search/branches/Branch_3_1/src/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
Log:
HSEARCH-357 IdBridge being applied on null entity during purgeAll()
Modified: search/branches/Branch_3_1/src/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
===================================================================
--- search/branches/Branch_3_1/src/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2009-04-07 22:09:50 UTC (rev 16274)
+++ search/branches/Branch_3_1/src/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2009-04-07 22:13:05 UTC (rev 16275)
@@ -297,28 +297,24 @@
return;
}
- String idInString = idBridge.objectToString( id );
if ( workType == WorkType.ADD ) {
+ String idInString = idBridge.objectToString( id );
queue.add( createAddWork( entityClass, entity, id, idInString, false ) );
}
else if ( workType == WorkType.DELETE || workType == WorkType.PURGE ) {
+ String idInString = idBridge.objectToString( id );
queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
}
else if ( workType == WorkType.PURGE_ALL ) {
queue.add( new PurgeAllLuceneWork( entityClass ) );
}
else if ( workType == WorkType.UPDATE || workType == WorkType.COLLECTION ) {
- /**
- * even with Lucene 2.1, use of indexWriter to update is not an option
- * We can only delete by term, and the index doesn't have a term that
- * uniquely identify the entry.
- * But essentially the optimization we are doing is the same Lucene is doing, the only extra cost is the
- * double file opening.
- */
+ String idInString = idBridge.objectToString( id );
queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
queue.add( createAddWork( entityClass, entity, id, idInString, false ) );
}
else if ( workType == WorkType.INDEX ) {
+ String idInString = idBridge.objectToString( id );
queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
queue.add( createAddWork( entityClass, entity, id, idInString, true ) );
}
15 years, 7 months
Hibernate SVN: r16274 - search/trunk/src/main/java/org/hibernate/search/engine.
by hibernate-commits@lists.jboss.org
Author: sannegrinovero
Date: 2009-04-07 18:09:50 -0400 (Tue, 07 Apr 2009)
New Revision: 16274
Modified:
search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
Log:
HSEARCH-357 IdBridge being applied on null entity during purgeAll()
Modified: search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2009-04-07 21:37:10 UTC (rev 16273)
+++ search/trunk/src/main/java/org/hibernate/search/engine/DocumentBuilderIndexedEntity.java 2009-04-07 22:09:50 UTC (rev 16274)
@@ -295,28 +295,24 @@
return;
}
- String idInString = idBridge.objectToString( id );
if ( workType == WorkType.ADD ) {
+ String idInString = idBridge.objectToString( id );
queue.add( createAddWork( entityClass, entity, id, idInString, false ) );
}
else if ( workType == WorkType.DELETE || workType == WorkType.PURGE ) {
+ String idInString = idBridge.objectToString( id );
queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
}
else if ( workType == WorkType.PURGE_ALL ) {
queue.add( new PurgeAllLuceneWork( entityClass ) );
}
else if ( workType == WorkType.UPDATE || workType == WorkType.COLLECTION ) {
- /**
- * even with Lucene 2.1, use of indexWriter to update is not an option
- * We can only delete by term, and the index doesn't have a term that
- * uniquely identify the entry.
- * But essentially the optimization we are doing is the same Lucene is doing, the only extra cost is the
- * double file opening.
- */
+ String idInString = idBridge.objectToString( id );
queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
queue.add( createAddWork( entityClass, entity, id, idInString, false ) );
}
else if ( workType == WorkType.INDEX ) {
+ String idInString = idBridge.objectToString( id );
queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
queue.add( createAddWork( entityClass, entity, id, idInString, true ) );
}
15 years, 7 months
Hibernate SVN: r16273 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/engine/xml and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-04-07 17:37:10 -0400 (Tue, 07 Apr 2009)
New Revision: 16273
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
Log:
HV-112
Implementations honours the ignore-annotation flags now
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-07 21:37:10 UTC (rev 16273)
@@ -90,10 +90,32 @@
*/
private final ConstraintHelper constraintHelper;
+ private Map<Class<?>, Boolean> ignoreAnnotationDefaults;
+ private Map<Class<?>, List<Member>> ignoreAnnotationOnMember;
+ private List<Class<?>> ignoreAnnotationOnClass;
+
public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
+ this(
+ beanClass,
+ constraintHelper,
+ new HashMap<Class<?>, Boolean>(),
+ new ArrayList<Class<?>>(),
+ new HashMap<Class<?>, List<Member>>()
+ );
+ }
+
+ public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper, Map<Class<?>, Boolean> ignoreAnnotationDefaults, List<Class<?>> ignoreAnnotationOnClass, Map<Class<?>, List<Member>> ignoreAnnotationOnMember) {
this.beanClass = beanClass;
this.constraintHelper = constraintHelper;
+ this.ignoreAnnotationDefaults = ignoreAnnotationDefaults;
+ this.ignoreAnnotationOnClass = ignoreAnnotationOnClass;
+ this.ignoreAnnotationOnMember = ignoreAnnotationOnMember;
+
createMetaData();
+
+ this.ignoreAnnotationDefaults = null;
+ this.ignoreAnnotationOnClass = null;
+ this.ignoreAnnotationOnMember = null;
}
public Class<T> getBeanClass() {
@@ -207,6 +229,9 @@
for ( Field field : clazz.getDeclaredFields() ) {
List<ConstraintDescriptorImpl> fieldMetadata = findConstraints( field );
for ( ConstraintDescriptorImpl constraintDescription : fieldMetadata ) {
+ if ( checkSkipAnnotationProcessing( clazz, field ) ) {
+ break;
+ }
ReflectionHelper.setAccessibility( field );
MetaConstraint<T, A> metaConstraint = new MetaConstraint<T, A>(
field, beanClass, constraintDescription
@@ -225,6 +250,9 @@
for ( Method method : clazz.getDeclaredMethods() ) {
List<ConstraintDescriptorImpl> methodMetadata = findConstraints( method );
for ( ConstraintDescriptorImpl constraintDescription : methodMetadata ) {
+ if ( checkSkipAnnotationProcessing( clazz, method ) ) {
+ break;
+ }
ReflectionHelper.setAccessibility( method );
MetaConstraint<T, A> metaConstraint = new MetaConstraint<T, A>(
method, beanClass, constraintDescription
@@ -239,6 +267,29 @@
}
}
+ private boolean checkSkipAnnotationProcessing(Class clazz, Member member) {
+ List<Member> ignoreAnnotationForFields = ignoreAnnotationOnMember.get( clazz );
+ boolean ignoreAnnotation;
+ if ( ignoreAnnotationForFields == null || !ignoreAnnotationForFields.contains( member ) ) {
+ ignoreAnnotation = ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz );
+ }
+ else {
+ ignoreAnnotation = ignoreAnnotationForFields.contains( member );
+ }
+ if ( ignoreAnnotation ) {
+ String type;
+ if ( member instanceof Field ) {
+ type = "Field";
+ }
+ else {
+ type = "Property";
+ }
+ log.debug( type + " level annotations are getting ignored for " + clazz.getName() + "." + member.getName() );
+ return true;
+ }
+ return false;
+ }
+
private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member) {
String name = ReflectionHelper.getPropertyName( member );
PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get(
@@ -256,6 +307,11 @@
}
private <A extends Annotation> void initClassConstraints(Class clazz) {
+ if ( ignoreAnnotationOnClass.contains( clazz ) ||
+ ( ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz ) ) ) {
+ log.debug( "Class level annotation are getting ignored for " + clazz.getName() );
+ return;
+ }
List<ConstraintDescriptorImpl> classMetadata = findClassLevelConstraints( clazz );
for ( ConstraintDescriptorImpl constraintDescription : classMetadata ) {
MetaConstraint<T, A> metaConstraint = new MetaConstraint<T, A>( clazz, constraintDescription );
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-07 21:37:10 UTC (rev 16273)
@@ -22,9 +22,9 @@
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
+import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
-import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -174,15 +174,28 @@
Field field = ReflectionHelper.getField( beanClass, fieldName );
boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false : fieldType.isIgnoreAnnotations();
if ( ignoreFieldAnnotation ) {
- ignoreAnnotationOnMember.put( beanClass, null );
+ addMemberToIgnoreList( beanClass, field );
}
for ( ConstraintType constraint : fieldType.getConstraint() ) {
- MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, field, defaultPackage );
+ MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
+ constraint, beanClass, field, defaultPackage
+ );
addMetaConstraint( beanClass, metaConstraint );
}
}
}
+ private void addMemberToIgnoreList(Class<?> beanClass, Member member) {
+ if ( ignoreAnnotationOnMember.get( beanClass ) == null ) {
+ List<Member> ignoredAnnotationOnMember = new ArrayList<Member>();
+ ignoredAnnotationOnMember.add( member );
+ ignoreAnnotationOnMember.put( beanClass, ignoredAnnotationOnMember );
+ }
+ else {
+ ignoreAnnotationOnMember.get( beanClass ).add( member );
+ }
+ }
+
private void parsePropertyLevelOverrides(List<GetterType> getters, Class<?> beanClass, String defaultPackage) {
for ( GetterType getter : getters ) {
String getterName = getter.getName();
@@ -192,10 +205,12 @@
Method method = ReflectionHelper.getMethod( beanClass, getterName );
boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false : getter.isIgnoreAnnotations();
if ( ignoreGetterAnnotation ) {
- ignoreAnnotationOnMember.put( beanClass, null );
+ addMemberToIgnoreList( beanClass, method );
}
for ( ConstraintType constraint : getter.getConstraint() ) {
- MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint, beanClass, method, defaultPackage );
+ MetaConstraint<?, ?> metaConstraint = createMetaConstraint(
+ constraint, beanClass, method, defaultPackage
+ );
addMetaConstraint( beanClass, metaConstraint );
}
}
@@ -451,7 +466,13 @@
private void initBeanMetaData() {
for ( Map.Entry<Class<?>, List<MetaConstraint<?, ?>>> entry : constraintMap.entrySet() ) {
- BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( entry.getKey(), constraintHelper );
+ BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl(
+ entry.getKey(),
+ constraintHelper,
+ ignoreAnnotationDefaults,
+ ignoreAnnotationOnClass,
+ ignoreAnnotationOnMember
+ );
for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
metaData.addMetaConstraint( metaConstraint );
}
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-07 20:49:32 UTC (rev 16272)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-07 21:37:10 UTC (rev 16273)
@@ -1,5 +1,8 @@
package org.hibernate.validation.engine.xml;
+import javax.validation.constraints.NotNull;
+import javax.validation.groups.Default;
+
/**
* @author Hardy Ferentschik
*/
@@ -9,13 +12,12 @@
private String firstname;
- //@NotNull(groups = Default.class)
private String lastname;
//@Pattern(regexp = "[0-9 -]?", groups = Optional.class)
private String phoneNumber;
-
+ @NotNull(groups = Default.class)
public String getFirstname() {
return firstname;
}
Modified: validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-07 20:49:32 UTC (rev 16272)
+++ validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-07 21:37:10 UTC (rev 16273)
@@ -3,7 +3,7 @@
xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
<default-package>org.hibernate.validation.engine.xml</default-package>
<bean class="User" ignore-annotations="false">
- <class ignore-annotations="false">
+ <class ignore-annotations="true">
<group-sequence>
<value>value0</value>
</group-sequence>
@@ -39,7 +39,7 @@
</element-->
</constraint>
</field>
- <getter name="firstname">
+ <getter name="firstname" ignore-annotations="true">
<valid/>
<constraint annotation="javax.validation.constraints.Size">
<message>Size is limited!</message>
15 years, 7 months
Hibernate SVN: r16272 - in search/branches/Branch_3_1: src/java/org/hibernate/search/backend/impl and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: sannegrinovero
Date: 2009-04-07 16:49:32 -0400 (Tue, 07 Apr 2009)
New Revision: 16272
Added:
search/branches/Branch_3_1/src/java/org/hibernate/search/event/IndexWorkFlushEventListener.java
search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/
search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusLine.java
search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java
search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java
search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java
Modified:
search/branches/Branch_3_1/doc/reference/en/modules/configuration.xml
search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java
search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java
search/branches/Branch_3_1/src/java/org/hibernate/search/event/EventListenerRegister.java
search/branches/Branch_3_1/src/test/org/hibernate/search/test/TestCase.java
search/branches/Branch_3_1/src/test/org/hibernate/search/test/classloading/NoAnnotationsTest.java
Log:
HSEARCH-178 for 3.1 branch
Modified: search/branches/Branch_3_1/doc/reference/en/modules/configuration.xml
===================================================================
--- search/branches/Branch_3_1/doc/reference/en/modules/configuration.xml 2009-04-07 20:20:12 UTC (rev 16271)
+++ search/branches/Branch_3_1/doc/reference/en/modules/configuration.xml 2009-04-07 20:49:32 UTC (rev 16272)
@@ -600,7 +600,8 @@
<para>To enable Hibernate Search in Hibernate Core (ie. if you don't use
Hibernate Annotations), add the
<literal>FullTextIndexEventListener</literal> for the following six
- Hibernate events.</para>
+ Hibernate events and add the <literal>IndexWorkFlushEventListener</literal> after
+ the default <literal>DefaultFlushEventListener</literal>, as in the following example.</para>
<example>
<title>Explicitly enabling Hibernate Search by configuring the
@@ -609,24 +610,28 @@
<programlisting><hibernate-configuration>
<session-factory>
...
- <event type="post-update"/>
+ <event type="post-update">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-insert"/>
+ <event type="post-insert">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-delete"/>
+ <event type="post-delete">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-collection-recreate"/>
+ <event type="post-collection-recreate">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-collection-remove"/>
+ <event type="post-collection-remove">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-collection-update"/>
+ <event type="post-collection-update">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
+ <event type="flush">
+ <listener class="org.hibernate.event.def.DefaultFlushEventListener"/>
+ <listener class="org.hibernate.search.event.IndexWorkFlushEventListener"/>
+ </event>
</session-factory>
</hibernate-configuration></programlisting>
</example>
Modified: search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java
===================================================================
--- search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java 2009-04-07 20:20:12 UTC (rev 16271)
+++ search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/EventSourceTransactionContext.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -2,35 +2,93 @@
package org.hibernate.search.backend.impl;
import java.io.Serializable;
+
import javax.transaction.Synchronization;
+import org.hibernate.AssertionFailure;
import org.hibernate.Transaction;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.FlushEventListener;
import org.hibernate.search.backend.TransactionContext;
-import org.hibernate.event.EventSource;
+import org.hibernate.search.event.IndexWorkFlushEventListener;
+import org.hibernate.search.util.LoggerFactory;
+import org.slf4j.Logger;
/**
* Implementation of the transactional context on top of an EventSource (Session)
*
* @author Navin Surtani - navin(a)surtani.org
+ * @author Emmanuel Bernard
+ * @author Sanne Grinovero
*/
public class EventSourceTransactionContext implements TransactionContext, Serializable {
- EventSource eventSource;
+
+ private static final Logger log = LoggerFactory.make();
+
+ private final EventSource eventSource;
+ private final IndexWorkFlushEventListener flushListener;
+ //constructor time is too early to define the value of realTxInProgress,
+ //postpone it, otherwise doing
+ // " openSession - beginTransaction "
+ //will behave as "out of transaction" in the whole session lifespan.
+ private Boolean realTxInProgress = null;
+
public EventSourceTransactionContext(EventSource eventSource) {
this.eventSource = eventSource;
+ this.flushListener = findIndexWorkFlushEventListener();
}
public Object getTransactionIdentifier() {
- return eventSource.getTransaction();
+ if ( isRealTransactionInProgress() ) {
+ return eventSource.getTransaction();
+ }
+ else {
+ return eventSource;
+ }
}
public void registerSynchronization(Synchronization synchronization) {
- Transaction transaction = eventSource.getTransaction();
- transaction.registerSynchronization( synchronization );
+ if ( isRealTransactionInProgress() ) {
+ Transaction transaction = eventSource.getTransaction();
+ transaction.registerSynchronization( synchronization );
+ }
+ else {
+ if ( flushListener != null ) {
+ flushListener.addSynchronization( eventSource, synchronization );
+ }
+ else {
+ //It appears we are flushing out of transaction and have no way to perform the index update
+ //Not expected: see check in isTransactionInProgress()
+ throw new AssertionFailure( "On flush out of transaction: IndexWorkFlushEventListener not registered" );
+ }
+ }
}
+
+ private IndexWorkFlushEventListener findIndexWorkFlushEventListener() {
+ FlushEventListener[] flushEventListeners = eventSource.getListeners().getFlushEventListeners();
+ for (FlushEventListener listener : flushEventListeners) {
+ if ( listener.getClass().equals( IndexWorkFlushEventListener.class ) ) {
+ return (IndexWorkFlushEventListener) listener;
+ }
+ }
+ log.debug( "No IndexWorkFlushEventListener was registered" );
+ return null;
+ }
+ //The code is not really fitting the method name;
+ //(unless you consider a flush as a mini-transaction)
+ //This is because we want to behave as "inTransaction" if the flushListener is registered.
public boolean isTransactionInProgress() {
- return eventSource.isTransactionInProgress();
+ // either it is a real transaction, or if we are capable to manage this in the IndexWorkFlushEventListener
+ return isRealTransactionInProgress() || flushListener != null;
}
-
+
+ private boolean isRealTransactionInProgress() {
+ if ( realTxInProgress == null ) {
+ realTxInProgress = eventSource.isTransactionInProgress();
+ }
+ return realTxInProgress;
+ }
+
}
Modified: search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java
===================================================================
--- search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java 2009-04-07 20:20:12 UTC (rev 16271)
+++ search/branches/Branch_3_1/src/java/org/hibernate/search/backend/impl/TransactionalWorker.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -1,71 +1,83 @@
-//$Id$
-package org.hibernate.search.backend.impl;
-
-import java.util.Properties;
-
-import javax.transaction.Synchronization;
-
-import org.hibernate.search.backend.QueueingProcessor;
-import org.hibernate.search.backend.Work;
-import org.hibernate.search.backend.WorkQueue;
-import org.hibernate.search.backend.Worker;
-import org.hibernate.search.backend.TransactionContext;
-import org.hibernate.search.engine.SearchFactoryImplementor;
-import org.hibernate.search.util.WeakIdentityHashMap;
-
-/**
- * Queue works per transaction.
- * If out of transaction, the work is executed right away
- * <p/>
- * When <code>hibernate.search.worker.type</code> is set to <code>async</code>
- * the work is done in a separate thread (threads are pooled)
- *
- * @author Emmanuel Bernard
- */
-public class TransactionalWorker implements Worker {
- //not a synchronized map since for a given transaction, we have not concurrent access
- protected final WeakIdentityHashMap<Object, Synchronization> synchronizationPerTransaction = new WeakIdentityHashMap<Object, Synchronization>();
- private QueueingProcessor queueingProcessor;
-
- public void performWork(Work work, TransactionContext transactionContext) {
- if ( transactionContext.isTransactionInProgress() ) {
- Object transaction = transactionContext.getTransactionIdentifier();
- PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
- synchronizationPerTransaction.get( transaction );
- if ( txSync == null || txSync.isConsumed() ) {
- txSync = new PostTransactionWorkQueueSynchronization(
- queueingProcessor, synchronizationPerTransaction
- );
- transactionContext.registerSynchronization( txSync );
- synchronizationPerTransaction.put( transaction, txSync );
- }
- txSync.add( work );
- }
- else {
- WorkQueue queue = new WorkQueue( 2 ); //one work can be split
- queueingProcessor.add( work, queue );
- queueingProcessor.prepareWorks( queue );
- queueingProcessor.performWorks( queue );
- }
- }
-
- public void initialize(Properties props, SearchFactoryImplementor searchFactory) {
- this.queueingProcessor = new BatchedQueueingProcessor( searchFactory, props );
- }
-
- public void close() {
- queueingProcessor.close();
- }
-
- public void flushWorks(TransactionContext transactionContext) {
- if ( transactionContext.isTransactionInProgress() ) {
- Object transaction = transactionContext.getTransactionIdentifier();
- PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
- synchronizationPerTransaction.get( transaction );
- if ( txSync != null && !txSync.isConsumed() ) {
- txSync.flushWorks();
- }
- }
- }
-
-}
+//$Id$
+package org.hibernate.search.backend.impl;
+
+import java.util.Properties;
+
+import javax.transaction.Synchronization;
+
+import org.hibernate.search.backend.QueueingProcessor;
+import org.hibernate.search.backend.Work;
+import org.hibernate.search.backend.WorkQueue;
+import org.hibernate.search.backend.Worker;
+import org.hibernate.search.backend.TransactionContext;
+import org.hibernate.search.engine.SearchFactoryImplementor;
+import org.hibernate.search.util.LoggerFactory;
+import org.hibernate.search.util.WeakIdentityHashMap;
+import org.slf4j.Logger;
+
+/**
+ * Queue works per transaction.
+ * If out of transaction, the work is executed right away
+ * <p/>
+ * When <code>hibernate.search.worker.type</code> is set to <code>async</code>
+ * the work is done in a separate thread (threads are pooled)
+ *
+ * @author Emmanuel Bernard
+ */
+public class TransactionalWorker implements Worker {
+
+ //note: there is one Worker instance per SearchFactory, reused concurrently for all sessions.
+
+ private static final Logger log = LoggerFactory.make();
+
+ //FIXME: discuss the next line! it looks like there actually is concurrent access
+ //not a synchronized map since for a given transaction, we have not concurrent access
+ protected final WeakIdentityHashMap<Object, Synchronization> synchronizationPerTransaction = new WeakIdentityHashMap<Object, Synchronization>();
+ private QueueingProcessor queueingProcessor;
+
+ public void performWork(Work work, TransactionContext transactionContext) {
+ if ( transactionContext.isTransactionInProgress() ) {
+ Object transactionIdentifier = transactionContext.getTransactionIdentifier();
+ PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
+ synchronizationPerTransaction.get( transactionIdentifier );
+ if ( txSync == null || txSync.isConsumed() ) {
+ txSync = new PostTransactionWorkQueueSynchronization(
+ queueingProcessor, synchronizationPerTransaction
+ );
+ transactionContext.registerSynchronization( txSync );
+ synchronizationPerTransaction.put( transactionIdentifier, txSync );
+ }
+ txSync.add( work );
+ }
+ else {
+ // this is a workaround: isTransactionInProgress should return "true"
+ // for correct configurations.
+ log.warn( "It appears changes are being pushed to the index out of a transaction. " +
+ "Register the IndexWorkFlushEventListener listener on flush to correctly manage Collections!" );
+ WorkQueue queue = new WorkQueue( 2 ); //one work can be split
+ queueingProcessor.add( work, queue );
+ queueingProcessor.prepareWorks( queue );
+ queueingProcessor.performWorks( queue );
+ }
+ }
+
+ public void initialize(Properties props, SearchFactoryImplementor searchFactory) {
+ this.queueingProcessor = new BatchedQueueingProcessor( searchFactory, props );
+ }
+
+ public void close() {
+ queueingProcessor.close();
+ }
+
+ public void flushWorks(TransactionContext transactionContext) {
+ if ( transactionContext.isTransactionInProgress() ) {
+ Object transaction = transactionContext.getTransactionIdentifier();
+ PostTransactionWorkQueueSynchronization txSync = ( PostTransactionWorkQueueSynchronization )
+ synchronizationPerTransaction.get( transaction );
+ if ( txSync != null && !txSync.isConsumed() ) {
+ txSync.flushWorks();
+ }
+ }
+ }
+
+}
Modified: search/branches/Branch_3_1/src/java/org/hibernate/search/event/EventListenerRegister.java
===================================================================
--- search/branches/Branch_3_1/src/java/org/hibernate/search/event/EventListenerRegister.java 2009-04-07 20:20:12 UTC (rev 16271)
+++ search/branches/Branch_3_1/src/java/org/hibernate/search/event/EventListenerRegister.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -94,7 +94,13 @@
new PostCollectionUpdateEventListener[] { searchListener }
)
);
-
+ // Adding IndexWorkFlushEventListener to manage events out-of-transaction
+ if ( ! isFlushEventListenerRegistered( listeners.getFlushEventListeners() ) ) {
+ listeners.setFlushEventListeners( appendToArray(
+ listeners.getFlushEventListeners(),
+ new IndexWorkFlushEventListener()
+ ) );
+ }
}
/**
@@ -159,4 +165,19 @@
}
return false;
}
+
+ /**
+ * Verifies if an IndexWorkFlushEventListener is contained in the array of listeners.
+ * @param listeners
+ * @return true if it found in the listeners, false otherwise.
+ */
+ private static boolean isFlushEventListenerRegistered(Object[] listeners) {
+ for ( Object eventListener : listeners ) {
+ if ( IndexWorkFlushEventListener.class == eventListener.getClass() ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
Added: search/branches/Branch_3_1/src/java/org/hibernate/search/event/IndexWorkFlushEventListener.java
===================================================================
--- search/branches/Branch_3_1/src/java/org/hibernate/search/event/IndexWorkFlushEventListener.java (rev 0)
+++ search/branches/Branch_3_1/src/java/org/hibernate/search/event/IndexWorkFlushEventListener.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -0,0 +1,61 @@
+// $Id$
+package org.hibernate.search.event;
+
+import java.io.Serializable;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+
+import org.hibernate.AssertionFailure;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.event.EventSource;
+import org.hibernate.event.FlushEvent;
+import org.hibernate.event.FlushEventListener;
+import org.hibernate.search.util.LoggerFactory;
+import org.slf4j.Logger;
+
+/**
+ * FlushEventListener to make sure the indexes are updated right after the hibernate flush,
+ * avoiding object loading during a flush. Not needed during transactions.
+ *
+ * @author Sanne Grinovero
+ */
+public final class IndexWorkFlushEventListener implements FlushEventListener, Serializable {
+
+ private static final Logger log = LoggerFactory.make();
+
+ private final ConcurrentHashMap<Session, Synchronization> synchronizationPerTransaction
+ = new ConcurrentHashMap<Session, Synchronization>();
+
+ public IndexWorkFlushEventListener() {
+ }
+
+ public void onFlush(FlushEvent event) throws HibernateException {
+ Session session = event.getSession();
+ Synchronization synchronization = synchronizationPerTransaction.get( session );
+ if ( synchronization != null ) {
+ log.debug( "flush event causing index update out of transaction" );
+ synchronizationPerTransaction.remove( session );
+ synchronization.beforeCompletion();
+ synchronization.afterCompletion( Status.STATUS_COMMITTED );
+ }
+ }
+
+ public void addSynchronization(EventSource eventSource, Synchronization synchronization) {
+ Synchronization previousSync = synchronizationPerTransaction.put( eventSource, synchronization );
+ if ( previousSync != null ) {
+ throw new AssertionFailure( "previous registered sync not discarded in IndexWorkFlushEventListener" );
+ }
+ }
+
+ /*
+ * Might want to implement AutoFlushEventListener in future?
+ public void onAutoFlush(AutoFlushEvent event) throws HibernateException {
+ // Currently not needed as auto-flush is not happening
+ // when out of transaction.
+ }
+ */
+
+}
Property changes on: search/branches/Branch_3_1/src/java/org/hibernate/search/event/IndexWorkFlushEventListener.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: search/branches/Branch_3_1/src/test/org/hibernate/search/test/TestCase.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/TestCase.java 2009-04-07 20:20:12 UTC (rev 16271)
+++ search/branches/Branch_3_1/src/test/org/hibernate/search/test/TestCase.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -13,6 +13,9 @@
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
+import org.hibernate.event.FlushEventListener;
+import org.hibernate.event.def.DefaultFlushEventListener;
+import org.hibernate.search.event.IndexWorkFlushEventListener;
/**
* A modified base class for tests without annotations.
@@ -143,9 +146,15 @@
}
protected void configure(Configuration cfg) {
+ //needs to register all event listeners:
cfg.setListener( "post-update", "org.hibernate.search.event.FullTextIndexEventListener" );
cfg.setListener( "post-insert", "org.hibernate.search.event.FullTextIndexEventListener" );
cfg.setListener( "post-delete", "org.hibernate.search.event.FullTextIndexEventListener" );
+ cfg.setListener( "post-collection-recreate", "org.hibernate.search.event.FullTextIndexEventListener" );
+ cfg.setListener( "post-collection-remove", "org.hibernate.search.event.FullTextIndexEventListener" );
+ cfg.setListener( "post-collection-update", "org.hibernate.search.event.FullTextIndexEventListener" );
+
+ cfg.setListeners( "flush", new FlushEventListener[]{new DefaultFlushEventListener(), new IndexWorkFlushEventListener()} );
cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
cfg.setProperty( org.hibernate.search.Environment.ANALYZER_CLASS, StopAnalyzer.class.getName() );
Modified: search/branches/Branch_3_1/src/test/org/hibernate/search/test/classloading/NoAnnotationsTest.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/classloading/NoAnnotationsTest.java 2009-04-07 20:20:12 UTC (rev 16271)
+++ search/branches/Branch_3_1/src/test/org/hibernate/search/test/classloading/NoAnnotationsTest.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -10,7 +10,6 @@
import org.hibernate.Transaction;
import org.hibernate.search.Search;
-
/**
* @author Hardy Ferentschik
*/
@@ -39,7 +38,28 @@
tx.commit();
s.close();
}
+
+ public void testFlushListenerRegistrationWithoutAnnotations() throws Exception {
+ // This test should pass even if the flushListener is not registered,
+ // as a workaround is done in code (you'll see a warning in logs).
+ Animal pinguin = new Animal();
+ pinguin.setName( "Penguin" );
+ Session s = openSession();
+ s.save( pinguin );
+ s.flush();
+ s.clear();
+
+ Transaction tx = s.beginTransaction();
+ tx = s.beginTransaction();
+ List results = Search.getFullTextSession( s ).createFullTextQuery(
+ new TermQuery( new Term( "name", "penguin" ) )
+ ).list();
+ assertEquals( 1, results.size() );
+ tx.commit();
+ s.close();
+ }
+
protected String[] getXmlFiles() {
return new String[] {
"org/hibernate/search/test/classloading/Animal.hbm.xml"
Added: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusLine.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusLine.java (rev 0)
+++ search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusLine.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -0,0 +1,87 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.IndexedEmbedded;
+import org.hibernate.search.annotations.Store;
+
+/**
+ * Test entity: BusLine have many BusStops: needed to verify
+ * indexing of a lazy-loaded collection in out-of-transaction use case.
+ *
+ * @author Sanne Grinovero
+ */
+@Entity
+@Indexed
+public class BusLine {
+
+ private Long id;
+ private String busLineName;
+ private Set<BusStop> stops = new HashSet<BusStop>();
+
+ @Id
+ @GeneratedValue
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Field(index=Index.NO,store=Store.YES)
+ public String getBusLineName() {
+ return busLineName;
+ }
+
+ public void setBusLineName(String busLine) {
+ this.busLineName = busLine;
+ }
+
+ @ManyToMany(cascade=CascadeType.PERSIST)
+ @IndexedEmbedded
+ public Set<BusStop> getStops() {
+ return stops;
+ }
+
+ public void setStops(Set<BusStop> stops) {
+ this.stops = stops;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((busLineName == null) ? 0 : busLineName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BusLine other = (BusLine) obj;
+ if (busLineName == null) {
+ if (other.busLineName != null)
+ return false;
+ } else if (!busLineName.equals(other.busLineName))
+ return false;
+ return true;
+ }
+
+}
Added: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java (rev 0)
+++ search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -0,0 +1,82 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+import org.hibernate.search.annotations.ContainedIn;
+import org.hibernate.search.annotations.Field;
+
+/**
+ * Test entity: BusStop is @ContainedIn BusLine
+ *
+ * @author Sanne Grinovero
+ */
+@Entity
+public class BusStop {
+
+ private Long id;
+ private String roadName;
+ private Set<BusLine> busses = new HashSet<BusLine>();
+
+ @Id
+ @GeneratedValue
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Field
+ public String getRoadName() {
+ return roadName;
+ }
+
+ public void setRoadName(String roadName) {
+ this.roadName = roadName;
+ }
+
+ @ManyToMany(mappedBy="stops")
+ @ContainedIn
+ public Set<BusLine> getBusses() {
+ return busses;
+ }
+
+ public void setBusses(Set<BusLine> busses) {
+ this.busses = busses;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((roadName == null) ? 0 : roadName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BusStop other = (BusStop) obj;
+ if (roadName == null) {
+ if (other.roadName != null)
+ return false;
+ } else if (!roadName.equals(other.roadName))
+ return false;
+ return true;
+ }
+
+}
Property changes on: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/BusStop.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java (rev 0)
+++ search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -0,0 +1,119 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import java.util.List;
+
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.TermQuery;
+import org.hibernate.Transaction;
+import org.hibernate.search.Environment;
+import org.hibernate.search.FullTextQuery;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.store.RAMDirectoryProvider;
+import org.hibernate.search.test.SearchTestCase;
+
+/**
+ * TestCase for HSEARCH-178 (Search hitting HHH-2763)
+ * Verifies that it's possible to index lazy loaded collections from
+ * indexed entities even when no transactions are used.
+ *
+ * @author Sanne Grinovero
+ */
+public class LazyCollectionsUpdatingTest extends SearchTestCase {
+
+ public void testUpdatingInTransaction() {
+ assertFindsByRoadName( "buonarroti" );
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ try {
+ Transaction tx = fullTextSession.beginTransaction();
+ BusStop busStop = (BusStop) fullTextSession.get( BusStop.class, 1L );
+ busStop.setRoadName( "new road" );
+ tx.commit();
+ }
+ catch (org.hibernate.AssertionFailure ass) {
+ fail( ass.getMessage() );
+ }
+ finally {
+ fullTextSession.close();
+ }
+ assertFindsByRoadName( "new" );
+ }
+
+ public void testUpdatingOutOfTransaction() {
+ assertFindsByRoadName( "buonarroti" );
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ try {
+ BusStop busStop = (BusStop) fullTextSession.get( BusStop.class, 1L );
+ busStop.setRoadName( "new road" );
+ fullTextSession.flush();
+ }
+ catch (org.hibernate.AssertionFailure ass) {
+ fail( ass.getMessage() );
+ }
+ finally {
+ fullTextSession.close();
+ }
+ assertFindsByRoadName( "new" );
+ }
+
+ public void assertFindsByRoadName(String analyzedRoadname) {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ TermQuery ftQuery = new TermQuery( new Term( "stops.roadName", analyzedRoadname ) );
+ FullTextQuery query = fullTextSession.createFullTextQuery( ftQuery, BusLine.class );
+ query.setProjection( "busLineName" );
+ assertEquals( 1, query.list().size() );
+ List results = query.list();
+ String resultName = (String) ((Object[])results.get(0))[0];
+ assertEquals( "Linea 64", resultName );
+ tx.commit();
+ fullTextSession.close();
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ BusLine bus = new BusLine();
+ bus.setBusLineName( "Linea 64" );
+ addBusStop( bus, "Stazione Termini" );
+ addBusStop( bus, "via Gregorio VII" );
+ addBusStop( bus, "via Alessandro III" );
+ addBusStop( bus, "via M.Buonarroti" );
+ session.persist( bus );
+ tx.commit();
+ } catch (Throwable t) {
+ if ( tx != null )
+ tx.rollback();
+ } finally {
+ session.close();
+ }
+ }
+
+ private void addBusStop(BusLine bus, String roadName) {
+ BusStop stop = new BusStop();
+ stop.setRoadName( roadName );
+ bus.getStops().add( stop );
+ stop.getBusses().add( bus );
+ }
+
+ // Test setup options - Entities
+ @Override
+ protected Class[] getMappings() {
+ return new Class[] { BusLine.class, BusStop.class };
+ }
+
+ // Test setup options - SessionFactory Properties
+ @Override
+ protected void configure(org.hibernate.cfg.Configuration configuration) {
+ super.configure( configuration );
+ cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
+ cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
+ }
+
+}
Property changes on: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/LazyCollectionsUpdatingTest.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java
===================================================================
--- search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java (rev 0)
+++ search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java 2009-04-07 20:49:32 UTC (rev 16272)
@@ -0,0 +1,90 @@
+// $Id$
+package org.hibernate.search.test.engine;
+
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.hibernate.Transaction;
+import org.hibernate.search.Environment;
+import org.hibernate.search.FullTextQuery;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.store.RAMDirectoryProvider;
+import org.hibernate.search.test.SearchTestCase;
+
+/**
+ * Verify index changes queued during a transaction are canceled
+ * when the transaction is rolled back.
+ *
+ * @author Sanne Grinovero
+ */
+public class RollbackTransactionTest extends SearchTestCase {
+
+ public void testTransactionBehaviour() {
+ assertEquals( 0, countBusLinesByFullText() );
+ assertEquals( 0, countBusLineByDatabaseCount() );
+ createBusLines( 5, true );
+ assertEquals( 0, countBusLinesByFullText() );
+ assertEquals( 0, countBusLineByDatabaseCount() );
+ createBusLines( 5, false );
+ assertEquals( 5, countBusLinesByFullText() );
+ assertEquals( 5, countBusLineByDatabaseCount() );
+ createBusLines( 7, true );
+ assertEquals( 5, countBusLinesByFullText() );
+ assertEquals( 5, countBusLineByDatabaseCount() );
+ createBusLines( 7, false );
+ assertEquals( 12, countBusLinesByFullText() );
+ assertEquals( 12, countBusLineByDatabaseCount() );
+ }
+
+ private void createBusLines(int number, boolean rollback) {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ for (int i=0; i<number; i++ ) {
+ BusLine line = new BusLine();
+ line.setBusLineName( "line " + i );
+ fullTextSession.persist( line );
+ }
+ if ( rollback ) {
+ tx.rollback();
+ }
+ else {
+ tx.commit();
+ }
+ fullTextSession.close();
+ }
+
+ public int countBusLinesByFullText() {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ org.apache.lucene.search.Query ftQuery = new MatchAllDocsQuery();
+ FullTextQuery query = fullTextSession.createFullTextQuery( ftQuery, BusLine.class );
+ int count = query.list().size();
+ tx.commit();
+ fullTextSession.close();
+ return count;
+ }
+
+ public int countBusLineByDatabaseCount() {
+ FullTextSession fullTextSession = Search.getFullTextSession( sessions.openSession() );
+ Transaction tx = fullTextSession.beginTransaction();
+ int count = fullTextSession.createCriteria( BusLine.class ).list().size();
+ tx.commit();
+ fullTextSession.close();
+ return count;
+ }
+
+ // Test setup options - Entities
+ @Override
+ protected Class[] getMappings() {
+ return new Class[] { BusLine.class, BusStop.class };
+ }
+
+ // Test setup options - SessionFactory Properties
+ @Override
+ protected void configure(org.hibernate.cfg.Configuration configuration) {
+ super.configure( configuration );
+ cfg.setProperty( "hibernate.search.default.directory_provider", RAMDirectoryProvider.class.getName() );
+ cfg.setProperty( Environment.ANALYZER_CLASS, SimpleAnalyzer.class.getName() );
+ }
+
+}
Property changes on: search/branches/Branch_3_1/src/test/org/hibernate/search/test/engine/RollbackTransactionTest.java
___________________________________________________________________
Name: svn:keywords
+ Id
15 years, 7 months