This is an internal documentation. There is a good chance you’re looking for something else. See Disclaimer.
Configuration¶
Spring / Spring boot manages and distributes instances of objects. These are called beans. Bean management and the opportunity for dependency injection are some of Spring’s main features. Spring collects bean instances and uses them at the appropriate time.
There are two main ways of how we create beans:
a class is annotated by
@Component
(or a derivative, e.g.@Listener
,@Service
,@RestResource
, …). Any class that is annotated that way will be automatically instantiated and made available to be injected.it is created by a
@Bean
annotated method in a@Configuration
class
With spring boot it is possible to create code that may be injected into other classes without an interface.
E.g.
@Component
public class TestService {
public String generateString() {
// ...
}
public void processString(String param) {
// ...
}
}
@Listener(filter = "User")
@ThreadScope
public class TestListener extends CollectingEntityListener {
private final TestService service;
public TestListener(TestService service) {
this.service = service;
}
}
If such a service should be available in another module, an “visible” interface in - for example - the api
package
may still be required.
@ThreadScope¶
If a bean should be recreated for each thread (e.g. CollectingEntityListeners) the annotation @ThreadScope
should be
used.
Accessing Beans¶
Beans will be automatically injected into @Autowired
annotated members, methods or as constructor parameters if
spring is able to unambiguously identify them. (E.g. if there is only one bean of the given type, or if the parameter
name is named like a specific implementation).
If there are multiple implementations of an interface that all need to be injected, @Autowired
can be used to
inject lists of beans.
Example:
public interface TestInterface {
String getString();
}
@Component
public class TestImplementationA implements TestInterface {
@Override
public String getString() {
return "A";
}
}
@Component
public class TestImplementationB implements TestInterface {
@Override
public String getString() {
return "B";
}
}
@Component
public class Test {
private final TestInterface testImplementationA;
private List<TestInterface> implementations;
public Test(TestInterface testImplementationA) { //TestImplementationA will be injected here
this.testImplementationA = testImplementationA;
}
@Autowired //will inject both TestImplementationA and TestImplementationB
public void setImplementations(List<TestInterface> implementations) {
this.implementations = implementations;
}
}
Naming a parameter / variable like a specific implementation can be used to get instances of objects in other modules. This is for example used to register specific validators in other modules.
@Bean
public EntitiesValidatorContribution pagePathUniquenessValidator(EntitiesValidator pathUniquenessValidator) {
EntitiesValidatorContribution contribution = new EntitiesValidatorContribution();
contribution.setValidator(pathUniquenessValidator);
contribution.setFilter("Page");
return contribution;
}
@Qualifier¶
If there are beans of a more generic type (e.g. String
), @Qualifier
can be used to distinguish them. This is
used to replace old “string contributions” as shown below:
// annotation class
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface DisabledLegacyAction {
}
// configuration in @Configuration classes
// ...
@Bean
@DisabledLegacyAction
public String disableCreateDebitorExportAction() {
return "nice2.optional.finance.CreateDebitorExportAction";
}
// ...
@Bean
@DisabledLegacyAction
public String disablePublishAllAction() {
return "nice2.dms.PublishAllAction";
}
// usage in component
//all String beans with Qualifier @DisabledLegacyAction will be autowired
@Autowired(required = false)
@DisabledLegacyAction
public void setDisabledLegacyActions(List<String> disabledLegacyActions) {
this.disabledLegacyActions.addAll(disabledLegacyActions);
}
File-References¶
To reference module-resources findModelResource
or findJavaResource
of
AppModule should be used. If file access is required in
@Configuration
classes AbstractConfiguration should
be extended to get access to its convenient findModelResource
method.
@Bean
public TemplateSnippetContributionsBuilder toccoTemplateSnippetsContributions() {
return TemplateSnippetContributionsBuilder.create()
.uniqueId("jira_issue_cellrenderer")
.label("templatesnippet.jira_issue_cellrenderer")
.freemarker(findModelResource("templatesnippet/jira_issue_cellrenderer.ftl"))
.categories("cellrenderer");
}
To access files from other modules, the module manager can be used to get the other module first:
@Bean
public LabelContentSynchronisationDescription address3660LabelContentDescription() {
AppModule reportingModule = moduleManager.getModule("nice.core.reporting");
LabelContentSynchronisationDescription description = new LabelContentSynchronisationDescription();
description.setIdentifier("zf_3660_address");
description.setModule("Address");
description.setLabelKey("report.Label_content.zf3660");
description.setFreemarker(findModelResource(reportingModule, "outputtemplate/labelcontents/content_3660.ftl"));
description.setLess(findModelResource(reportingModule, "outputtemplate/labelcontents/content_3660.less"));
return description;
}