or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

field-analysis.mdgeneral-predicates.mdimport-control.mdindex.mdjava-only-rules.mdmethod-validation.mdsource-predicates.md

java-only-rules.mddocs/

0

# Java-Only Rules

1

2

Utility methods that provide Java-only equivalents of standard ArchUnit rule definitions. Essential for mixed Java/Scala projects where ArchUnit's limited Scala support can cause analysis issues.

3

4

## Capabilities

5

6

### Java-Only Class Selection

7

8

Provides equivalent functionality to ArchUnit's standard rule definitions but restricted to Java classes only.

9

10

```java { .api }

11

/**

12

* Equivalent of ArchRuleDefinition.classes(), but only for Java classes

13

* @return ClassesThat builder for creating rules that apply only to Java classes

14

*/

15

public static ClassesThat<GivenClassesConjunction> javaClassesThat();

16

17

/**

18

* Equivalent of ArchRuleDefinition.classes() with predicate, but only for Java classes

19

* @param predicate Additional predicate to filter Java classes

20

* @return GivenClassesConjunction for building rules on filtered Java classes

21

*/

22

public static GivenClassesConjunction javaClassesThat(DescribedPredicate<JavaClass> predicate);

23

```

24

25

**Usage Examples:**

26

27

```java

28

import org.apache.flink.architecture.common.GivenJavaClasses;

29

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;

30

31

// Standard ArchUnit - may include Scala classes

32

ArchRule standardRule = classes()

33

.that().arePublic()

34

.should().haveSimpleNameNotContaining("Impl");

35

36

// Java-only equivalent - excludes Scala classes automatically

37

ArchRule javaOnlyRule = GivenJavaClasses.javaClassesThat()

38

.arePublic()

39

.should().haveSimpleNameNotContaining("Impl");

40

41

// With additional predicate

42

ArchRule serviceClassesRule = GivenJavaClasses.javaClassesThat(

43

clazz -> clazz.getSimpleName().endsWith("Service")

44

).should().notBeInterfaces();

45

```

46

47

### Java-Only Negative Rules

48

49

Provides "no classes" equivalents restricted to Java classes only.

50

51

```java { .api }

52

/**

53

* Equivalent of ArchRuleDefinition.noClasses(), but only for Java classes

54

* @return ClassesThat builder for creating negative rules on Java classes

55

*/

56

public static ClassesThat<GivenClassesConjunction> noJavaClassesThat();

57

58

/**

59

* Equivalent of ArchRuleDefinition.noClasses() with predicate, but only for Java classes

60

* @param predicate Additional predicate to filter Java classes

61

* @return GivenClassesConjunction for building negative rules on filtered Java classes

62

*/

63

public static GivenClassesConjunction noJavaClassesThat(

64

DescribedPredicate<JavaClass> predicate);

65

```

66

67

**Usage Examples:**

68

69

```java

70

// Ensure no Java classes violate naming conventions

71

ArchRule noImplInPublicApi = GivenJavaClasses.noJavaClassesThat()

72

.arePublic()

73

.should().haveSimpleNameContaining("Impl");

74

75

// Ensure no service classes are in wrong package

76

ArchRule noServicesInUtil = GivenJavaClasses.noJavaClassesThat(

77

clazz -> clazz.getSimpleName().endsWith("Service")

78

).should().resideInAPackage("..util..");

79

80

// Complex negative rule

81

ArchRule noPublicInternalClasses = GivenJavaClasses.noJavaClassesThat()

82

.arePublic()

83

.and().resideInAPackage("..internal..")

84

.should().exist();

85

```

86

87

## Java vs Scala Filtering

88

89

### Why Java-Only Rules are Necessary

90

91

```java

92

// Problem: Standard ArchUnit may analyze Scala classes incorrectly

93

ArchRule problematicRule = classes()

94

.that().haveSimpleNameEndingWith("$") // Scala generates $ classes

95

.should().bePackagePrivate(); // May fail on Scala artifacts

96

97

// Solution: Use Java-only rules

98

ArchRule safeRule = GivenJavaClasses.javaClassesThat()

99

.haveSimpleNameNotContaining("$") // No Scala artifacts

100

.should().followCustomNamingConvention();

101

```

102

103

### Integration with SourcePredicates

104

105

```java

106

import org.apache.flink.architecture.common.SourcePredicates;

107

108

// Double-layer protection against non-Java classes

109

ArchRule extraSafeRule = GivenJavaClasses.javaClassesThat(

110

SourcePredicates.areJavaClasses() // Additional Java-only filtering

111

).should().notAccessClassesThat().haveSimpleNameContaining("Scala");

112

```

113

114

## Advanced Usage Patterns

115

116

### Package Structure Validation

117

118

```java

119

// Validate Java package organization

120

ArchRule packageStructureRule = GivenJavaClasses.javaClassesThat()

121

.resideInAPackage("org.apache.flink.api..")

122

.should().onlyAccessClassesThat()

123

.resideInAnyPackage(

124

"org.apache.flink.api..",

125

"org.apache.flink.util..",

126

"java..",

127

"javax.."

128

);

129

130

// Ensure internal packages are not accessed by public API

131

ArchRule internalAccessRule = GivenJavaClasses.noJavaClassesThat()

132

.resideInAPackage("org.apache.flink.api..")

133

.should().accessClassesThat()

134

.resideInAPackage("..internal..");

135

```

136

137

### Class Type Validation

138

139

```java

140

// Validate abstract classes follow conventions

141

ArchRule abstractClassRule = GivenJavaClasses.javaClassesThat()

142

.areAbstract()

143

.and().areNotInterfaces()

144

.should().haveSimpleNameStartingWith("Abstract")

145

.orShould().haveSimpleNameEndingWith("Base");

146

147

// Validate interface naming

148

ArchRule interfaceNamingRule = GivenJavaClasses.javaClassesThat()

149

.areInterfaces()

150

.and().arePublic()

151

.should().haveSimpleNameNotEndingWith("Impl")

152

.andShould().haveSimpleNameNotStartingWith("I");

153

```

154

155

### Annotation-Based Rules

156

157

```java

158

// Validate deprecated classes are properly marked

159

ArchRule deprecatedClassRule = GivenJavaClasses.javaClassesThat()

160

.areAnnotatedWith(Deprecated.class)

161

.should().haveSimpleNameContaining("Deprecated")

162

.orShould().resideInAPackage("..deprecated..");

163

164

// Validate experimental features

165

ArchRule experimentalRule = GivenJavaClasses.javaClassesThat()

166

.areAnnotatedWith("org.apache.flink.annotation.Experimental")

167

.should().resideInAPackage("..experimental..")

168

.orShould().haveSimpleNameContaining("Experimental");

169

```

170

171

### Inheritance and Composition Rules

172

173

```java

174

// Validate service implementation hierarchy

175

ArchRule serviceHierarchyRule = GivenJavaClasses.javaClassesThat()

176

.haveSimpleNameEndingWith("ServiceImpl")

177

.should().implement("org.apache.flink.api.common.Service")

178

.andShould().bePackagePrivate();

179

180

// Validate utility classes are final

181

ArchRule utilityClassRule = GivenJavaClasses.javaClassesThat()

182

.haveSimpleNameEndingWith("Utils")

183

.should().beFinal()

184

.andShould().haveOnlyPrivateConstructors();

185

```

186

187

### Complex Architectural Rules

188

189

```java

190

// Validate layered architecture

191

ArchRule layeredArchitectureRule = GivenJavaClasses.javaClassesThat()

192

.resideInAPackage("..api..")

193

.should().onlyAccessClassesThat()

194

.resideInAnyPackage("..api..", "..spi..", "..util..", "java..")

195

.andShould().notAccessClassesThat()

196

.resideInAnyPackage("..internal..", "..impl..");

197

198

// Validate test utilities don't leak into production

199

ArchRule testUtilityRule = GivenJavaClasses.noJavaClassesThat()

200

.resideOutsideOfPackage("..test..")

201

.should().accessClassesThat()

202

.haveSimpleNameContaining("Test")

203

.orShould().accessClassesThat()

204

.resideInAPackage("..test..");

205

```

206

207

## Performance and Memory Benefits

208

209

### Reduced Analysis Scope

210

211

```java

212

// Memory-intensive: analyzes all classes including Scala artifacts

213

ArchRule memoryHeavyRule = classes()

214

.should().notAccessClassesThat().resideInAPackage("..internal..");

215

216

// Memory-optimized: analyzes only Java classes

217

ArchRule memoryOptimizedRule = GivenJavaClasses.javaClassesThat()

218

.should().notAccessClassesThat().resideInAPackage("..internal..");

219

```

220

221

### Integration with Import Options

222

223

```java

224

import org.apache.flink.architecture.common.ImportOptions;

225

226

// Complete Java-only analysis pipeline

227

JavaClasses javaOnlyClasses = new ClassFileImporter()

228

.withImportOption(new ImportOptions.ExcludeScalaImportOption())

229

.withImportOption(new ImportOptions.ExcludeShadedImportOption())

230

.importPackages("org.apache.flink");

231

232

// Apply Java-only rules to Java-only imports

233

ArchRule completeJavaRule = GivenJavaClasses.javaClassesThat()

234

.arePublic()

235

.should().onlyAccessClassesThat()

236

.areNotAnnotatedWith("org.apache.flink.annotation.Internal");

237

238

completeJavaRule.check(javaOnlyClasses);

239

```

240

241

## Design Principles

242

243

- **Scala Compatibility**: Designed to handle mixed Java/Scala codebases safely

244

- **Drop-in Replacement**: Provides exact equivalents to standard ArchUnit rule definitions

245

- **Performance**: Reduces analysis scope by excluding non-Java classes

246

- **Composability**: Works with all standard ArchUnit conditions and predicates

247

- **Safety**: Provides additional layer of protection against Scala-related analysis issues