/** * If the "value" entry contains both "DerivedTxConfig" AND "TxConfig", then the algorithm is * accidentally picking up shadowed annotations of the same type within the class hierarchy. Such * undesirable behavior would cause the logic in {@link * org.springframework.context.annotation.ProfileCondition} to fail. * * @see * org.springframework.core.env.EnvironmentSystemIntegrationTests#mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass */ @Test public void getAllAnnotationAttributesOnClassWithLocalAnnotationThatShadowsAnnotationFromSuperclass() { MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(DerivedTxConfig.class, TX_NAME); assertNotNull("Annotation attributes map for @Transactional on DerivedTxConfig", attributes); assertEquals("value for DerivedTxConfig.", asList("DerivedTxConfig"), attributes.get("value")); }
@Test public void getAllAnnotationAttributesOnClassWithLocalComposedAnnotationAndInheritedAnnotation() { MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(SubClassWithInheritedAnnotation.class, TX_NAME); assertNotNull( "Annotation attributes map for @Transactional on SubClassWithInheritedAnnotation", attributes); assertEquals(asList("composed2", "transactionManager"), attributes.get("qualifier")); }
@Test public void depthFirst() throws Exception { assertEquals( Collections.<Integer>emptyList(), SortingNode.<Integer>emptyRoot().depthFirst().collect(toList())); SortingNode<Integer> tree = new SortingNode.Builder<Integer>() // .childNode(100) .siblingNode(200) .childNode(210) .siblingNode(220) .parent() .siblingNode(300) .siblingNode(400) .childNode(410) .siblingNode(420) .siblingNode(430) .childNode(431) .build(); assertEquals( asList(100, 200, 210, 220, 300, 400, 410, 420, 430, 431), tree.depthFirst().collect(toList())); SortingNode<Integer> n400 = tree.getChildren().get(3); assertEquals(asList(400, 410, 420, 430, 431), n400.depthFirst().collect(toList())); }
@Test public void javaxAnnotationTypeViaFindMergedAnnotation() throws Exception { assertEquals( ResourceHolder.class.getAnnotation(Resource.class), findMergedAnnotation(ResourceHolder.class, Resource.class)); assertEquals( SpringAppConfigClass.class.getAnnotation(Resource.class), findMergedAnnotation(SpringAppConfigClass.class, Resource.class)); }
@Test public void findMergedAnnotationWithAttributeAliasesInTargetAnnotation() { Class<?> element = AliasedTransactionalComponentClass.class; AliasedTransactional annotation = findMergedAnnotation(element, AliasedTransactional.class); assertNotNull("@AliasedTransactional on " + element, annotation); assertEquals("TX value via synthesized annotation.", "aliasForQualifier", annotation.value()); assertEquals( "TX qualifier via synthesized annotation.", "aliasForQualifier", annotation.qualifier()); }
@Test public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception { Constructor<?> deprecatedCtor = Date.class.getConstructor(String.class); assertEquals( deprecatedCtor.getAnnotation(Deprecated.class), findMergedAnnotation(deprecatedCtor, Deprecated.class)); assertEquals( Date.class.getAnnotation(Deprecated.class), findMergedAnnotation(Date.class, Deprecated.class)); }
@Test public void buildNodeTree() throws Exception { SortingNode<String> root = new SortingNode.Builder<String>().build(); assertFalse(root.hasChild()); assertTrue(root.isRoot()); assertFalse(root.hasParent()); SortingNode<Integer> tree = new SortingNode.Builder<Integer>() // .childNode(100) .siblingNode(200) .childNode(210) .siblingNode(220) .parent() .siblingNode(300) .siblingNode(400) .childNode(410) .siblingNode(420) .siblingNode(430) .childNode(431) .build(); assertFalse(tree.hasParent()); assertTrue(tree.isRoot()); assertFalse(tree.hasParent()); String expected = "" + "*\n" + " 100\n" + " 200\n" + " 210\n" + " 220\n" + " 300\n" + " 400\n" + " 410\n" + " 420\n" + " 430\n" + " 431"; assertEquals(expected, tree.prettyPrint()); SortingNode<Integer> n410 = tree.getChildren().get(3).getChildren().get(0); assertFalse(n410.hasChild()); assertTrue(n410.hasParent()); assertFalse(n410.isRoot()); assertEquals("410", n410.prettyPrint()); }
@Test public void getMetaAnnotationTypesOnClassWithMetaDepth2() { Set<String> names = getMetaAnnotationTypes( ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class); assertEquals(names(TransactionalComponent.class, Transactional.class, Component.class), names); }
@Test public void findMergedAnnotationAttributesOnClassWithMetaAndLocalTxConfig() { AnnotationAttributes attributes = findMergedAnnotationAttributes(MetaAndLocalTxConfigClass.class, Transactional.class); assertNotNull("Should find @Transactional on MetaAndLocalTxConfigClass", attributes); assertEquals( "TX qualifier for MetaAndLocalTxConfigClass.", "localTxMgr", attributes.getString("qualifier")); }
@Test public void getMergedAnnotationAttributesOnClassWithLocalAnnotation() { Class<?> element = TxConfig.class; String name = TX_NAME; AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Annotation attributes for @Transactional on TxConfig", attributes); assertEquals("value for TxConfig.", "TxConfig", attributes.getString("value")); // Verify contracts between utility methods: assertTrue(isAnnotated(element, name)); }
@Test public void getAllAnnotationAttributesFavorsInheritedComposedAnnotationsOverMoreLocallyDeclaredComposedAnnotations() { MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(SubSubClassWithInheritedComposedAnnotation.class, TX_NAME); assertNotNull( "Annotation attributes map for @Transactional on SubSubClassWithInheritedComposedAnnotation", attributes); assertEquals(asList("composed1"), attributes.get("qualifier")); }
@Test public void findMergedAnnotationAttributesOnClassWithAttributeAliasInComposedAnnotationAndNestedAnnotationsInTargetAnnotation() { AnnotationAttributes attributes = assertComponentScanAttributes(TestComponentScanClass.class, "com.example.app.test"); Filter[] excludeFilters = attributes.getAnnotationArray("excludeFilters", Filter.class); assertNotNull(excludeFilters); List<String> patterns = stream(excludeFilters).map(Filter::pattern).collect(toList()); assertEquals(asList("*Test", "*Tests"), patterns); }
/** * Note: this functionality is required by {@link * org.springframework.context.annotation.ProfileCondition}. * * @see org.springframework.core.env.EnvironmentSystemIntegrationTests */ @Test public void getAllAnnotationAttributesOnClassWithMultipleComposedAnnotations() { MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(TxFromMultipleComposedAnnotations.class, TX_NAME); assertNotNull( "Annotation attributes map for @Transactional on TxFromMultipleComposedAnnotations", attributes); assertEquals( "value for TxFromMultipleComposedAnnotations.", asList("TxInheritedComposed", "TxComposed"), attributes.get("value")); }
@Test public void findAndSynthesizeAnnotationAttributesOnClassWithAttributeAliasesInTargetAnnotation() { String qualifier = "aliasForQualifier"; // 1) Find and merge AnnotationAttributes from the annotation hierarchy AnnotationAttributes attributes = findMergedAnnotationAttributes( AliasedTransactionalComponentClass.class, AliasedTransactional.class); assertNotNull("@AliasedTransactional on AliasedTransactionalComponentClass.", attributes); // 2) Synthesize the AnnotationAttributes back into the target annotation AliasedTransactional annotation = AnnotationUtils.synthesizeAnnotation( attributes, AliasedTransactional.class, AliasedTransactionalComponentClass.class); assertNotNull(annotation); // 3) Verify that the AnnotationAttributes and synthesized annotation are equivalent assertEquals("TX value via attributes.", qualifier, attributes.getString("value")); assertEquals("TX value via synthesized annotation.", qualifier, annotation.value()); assertEquals("TX qualifier via attributes.", qualifier, attributes.getString("qualifier")); assertEquals("TX qualifier via synthesized annotation.", qualifier, annotation.qualifier()); }
@Test public void deepSort() throws Exception { SortingNode<Integer> tree = new SortingNode.Builder<Integer>() // .childNode(200) .siblingNode(100) .childNode(110) .siblingNode(120) .parent() .siblingNode(400) .childNode(410) .siblingNode(430) .childNode(431) .parent() .siblingNode(420) .parent() .siblingNode(300) .build(); tree = tree.deepSort((a, b) -> b.getValue() - a.getValue()); String expected = "" + "*\n" + " 400\n" + " 430\n" + " 431\n" + " 420\n" + " 410\n" + " 300\n" + " 200\n" + " 100\n" + " 120\n" + " 110"; assertEquals(expected, tree.prettyPrint()); }
@Test public void getAllAnnotationAttributesOnClassWithLocalAnnotation() { MultiValueMap<String, Object> attributes = getAllAnnotationAttributes(TxConfig.class, TX_NAME); assertNotNull("Annotation attributes map for @Transactional on TxConfig", attributes); assertEquals("value for TxConfig.", asList("TxConfig"), attributes.get("value")); }