I have this generic interface to validate the request and throw custom exception. Then I have an abstract class which implements this interface, which will have the common validation shared across the request and the actual implementation class for each request which extends this abstract class. I have a factory method which returns a bean based on the request. When I run sonar lint, it is complaining on return type of the getValidator(Action action), the message is "Provide the parameterized type for this generic" . It is a major code smell and I want to get rid of it. Is there a better way to do this? Or should I just ignore it?
//Interface
#FunctionalInterface
public interface CustomValidation<T> {
/**
* Validate method to throw custom exception when bean validation fails
*
* #param t
*/
void validate(String clientId, T t);
}
//Abstract Class
public abstract class AbstractCustomValidation<T> implements CustomValidation<T> {
//do something
}
//Factory
#Component
public class CustomValidatorFactory {
#Autowired
#Qualifier("a")
private CustomValidation<A> a;
#Autowired
#Qualifier("b")
private CustomValidation<B> b;
#Autowired
#Qualifier("c")
private CustomValidation<C> c;
#Autowired
#Qualifier("d")
private CustomValidation<D> d;
public CustomValidation getValidator(Action action) {
switch (action) {
case A:
return a;
case B:
return b;
case C:
return c;
case D:
return d;
default:
return null;
}
}
}
Have you considered
public CustomValidation<?>
I have a question, a little bit theoretical:
Assume, I have the following classes :
interface ReportInterface {
void execute();
}
class Report implements ReportInterface {
private final Repository rep;
Report(Repository ref){
this.rep = ref;
}
public void execute(){
//do some logic
}
}
class ReportWithSetter implements ReportInterface {
private final Repository rep;
private String release;
ReportWithSetter(Repository ref){
rep = ref;
}
public void execute(){
if (release == null) throw IlligalArgumentException("release is not specified");
//do some logic
}
public void setRelease(String release){
this.release=release;
}
}
The second report needs an additional parameter release to work properly, but my interface is defined without parameters for execute method, so I work around it with a setter method, so it would look like:
ReportWithSetter rep2 = new ReportWithSetter (rep);
rep.setRelease("R1.1");
rep.execute();
So I don't like this additional rep.setRelease. I looks weird and artificial - a user of this class may be confused, and for example, if I make the class as a singleton bean in Spring, it is a source of potential error, if it is requested for the second time and somebody forgets to trigger rep.setRelease for the second time. Besides putting it into constructor (I want to make it a spring bean), what would be the best practice to handling this situation?
Assuming you are allowed to change the interface, here are a few solutions I can think of:
Solution #1
void execute(Optional<String> release);
or
void execute(#Nullable String release);
and then use them for Report class as execute(Optional.empty()) or execute(null).
Solution #2
void execute(String... release);
and then use it for Report class as execute() and for ReportWithSetter class as execute("R1.1").
Solution #3
Define both void execute(); and void execute(String release); in the interface. Then while implementing, throw UnsupportedOperationException in the method you don't need. For example, in Report class, you would do:
public void execute(){
//do some logic
}
public void execute(String release){
throw new UnsupportedOperationException("Use the overloaded method");
}
You can also make both these methods as default in the interface, so your implementation classes don't have to worry about implementing the unsupported method.
Use whichever is most readable and maintainable for you.
Solution 1: Spring Dependency Injection - Field Injection:
Spring's Dependency Injection works with reflection, so Setter methods are not required.
So if you make your Report class a Spring Bean and use #Autowired to inject another bean, then the Setter method is not required.
It would look like this:
#Component
class ReportWithRelease implements ReportInterface {
#Autowired private final Repository rep;
#Autowired private Release release;
public void execute(){
if (release == null) throw IlligalArgumentException("release is not specified");
//do some logic
}
}
I changed "String release" to "Release release", because making a bean of "String" would be also strange. So the "Release" class would have to contain your "String release".
If "String release" contains only some configured value, which does not change at runtime. Then you can use #Value to read its String value from a properties file.
Solution 2: Spring Constructor Injection:
Constructor injection is another option, which is even more recommended.
Then your Report bean would look like this:
#Component
class ReportWithRelease implements ReportInterface {
private Repository rep;
private Release release;
#Autowired
public ReportWithRelease(Repository rep, Release release) {
this.rep = rep;
this.release = release;
}
public void execute(){
if (release == null) throw IlligalArgumentException("release is not specified");
//do some logic
}
}
Factory method patterns are good if you want to create instances of different classes of same interface.
class MyFactory {
ReportInterface createInstance(Class clazz, String... args) {
if (Report.class.equals(clazz)) {
return new Report();
}
if (ReportWithSetter.class.equals(clazz)) {
return new ReportWithSetter(args[0]);
}
throw new IllegalArgumentException(clazz.getName());
}
}
Spring of course offers autowiring, but introducing #AutoWire should be done for systematic purposes.
Here you can do with a two-stage execute, a factory.
class ReportFactory /*ReportWithSetter*/ {
private final Repository rep;
private final String release;
private final ReportInterface report = ...;
ReportFactory (Repository rep, String release) {
this.rep = rep;
this.release = release;
}
public ReportInterface report() {
return report;
}
}
new ReportFactory(rep, release).execute();
In the testing framework I'm using, there is a Precondition annotation that takes a class and calls call() method in it at runtime.
Core Modules of the Testing Framework:
Precondition Annotation
public #interface Precondition {
Class<? extends Scriptlet<? extends Context>> scriptlet();
String value() default Constants.EMPTY_STRING;
}
Scriptlet
public interface Scriptlet<V> extends Callable<V> {
}
Context
public interface Context {
}
If I pass the following precondition class to Precondition annotation there will be no errors.
CommonContextInit precondition class
class CommonContextInit implements Scriptlet<DataModel>{
CommonContextInit(Object script,String value){
}
#override
public DataModel call() throws Exception {
return null;
}
}
Script
#Precondition(scriptlet=CommonContextInit.class)
But I want to make CommonContextInit a generic where user can pass the type of the scriptlet so I changed the CommonContextInit class as follows
CommonContextInit precondition class
class CommonContextInit<T extends Context> implements Scriptlet<T>{
CommonContextInit(Object script,String value){
}
#override
public T call() throws Exception {
return null;
}
}
But the issue here is I have no idea how to pass the class to Precondition. The following I have tried but looks like it's totally invalid syntax.
// ERROR: The annotation #Precondition is disallowed for this location.
#Precondition(scriptlet=CommonContextInit<DataModel>.class)
How should I pass the Class of CommonContextInit<DataModel> to Precondition?
To extend my comment you shall have something like
class DataModelInstance extends CommonContextInit<DataModel> implements Scriptlet<DataModel>{
DataModelInstance(Object script,String value){
super(script, value);
}
//other overrides
}
and then call #Precondition(scriptlet=DataModelInstance.class)
Has anyone seen a pattern whereby Java constructor parameters are created using a DTO object and then injected into the class using Spring? I believe it is an anti-pattern but am curious if there is a reasonable case where it could be used.
In my mind the ideal thing to do is refactor the code so the need for the single constructor object is redundant.
What's everyones thoughts?
My particular example is of the form:
#Service
public class MyClass {
private MyClassConstructorDto constructorDependencyContainer;
#Autowired
public MyClass(MyClassConstructorDto constructorDependencyContainer) {
this.constructorDependencyContainer = constructorDependencyContainer;
}
public void doSomething() {
constructorDependencyContainer.getCoolDependency().performThing();
}
}
with supporting class
#Component
public class MyClassConstructorDto {
private CoolDependency coolDependency;
public MyClassConstructorDto(CoolDependency coolDependency) {
this.coolDependency = coolDependency;
}
public CoolDependency getCoolDependency() {
return coolDependency;
}
}
The project I'm working on is a spring boot one and I need to migrate, from an EJB project, multiple implementations of the same interface.
There's a job that needs to use all of this instances and we would like to use a flexible implementations like the one supported in java ejbs:
#Inject
private #Any
Instance<FleetAnalyzerProvider> fleetAnalyzerProviders;
In the source project, it is used a provider builder:
private void initializeProvider(String type) {
try {
final DeviceTypesProviderBuilder providerBuilder = new DeviceTypesProviderBuilder(type);
final Instance qualifiedInstance = this.fleetAnalyzerProviders.select(providerBuilder);
this.analyzerProvider = (FleetAnalyzerProvider) qualifiedInstance.get();
} catch (final Exception e) {
this.logger.error("[initializeProvider] Failed for type [{}] due to: {}", type, e);
}
}
where DeviceTypesProviderBuilder is:
public class DeviceTypesProviderBuilder extends AnnotationLiteral<DeviceTypes> implements DeviceTypes {
private final Type type;
public DeviceTypesProviderBuilder(String type) {
this.type = DeviceTypes.Type.getEnum(type);
}
#Override
public Type value() {
return type;
}
}
And DeviceTypes:
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, PARAMETER, FIELD, TYPE})
public #interface DeviceTypes {
Type value();
enum Type {
...
}
}
Is there a similar option in spring?
I saw a post (Autowire reference beans into list by type) with a syntax like this:
#Autowired
private FleetAnalyzerProvider[] fleetAnalyzerProviders;
But then how can I identify the correct provider?
The examples in the linked spring documentations are too simple and does not explicitly explain this particular possibility.