how to make dependency injection in spring java [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 months ago.
Improve this question
i have code bellow, i code without dependency injection,
i still dont get point what is advantage using dependency injection
interface class
#Component
public interface TextWriter {
public String WriteText(String s);
}
class one
public class YonoWriter implements TextWriter{
#Override
public String WriteText(String s) {
return s + " 1 ";
}
}
class two
public class Yono2Writer {
TextWriter text;
Yono2Writer(){
text = new YonoWriter();
}
public String hello(String s){
return this.text.WriteText(" 2 ") + s;
}
}
final class
#RestController
public class Yono3Writer {
Yono2Writer text;
Yono3Writer(){
text = new Yono2Writer();
}
#GetMapping("/")
public String hello2(){
return this.text.hello("3");
}
}
and the result is 2 1 3 and what is expected is 123 and how to implement dependency injection there ?

If you want to learn what more about dependency injection (DI) check spring docs
The summary of DI or IoC (inversion of control) is that the component defines the dependency and then the spring context injects a proper instance of the dependency, hence inversion of control. So instead of:
#RestController
public class Yono3Writer {
Yono2Writer text; // <- 1. component defines the dependency
Yono3Writer(){
text = new Yono2Writer(); // <- 2. component creates the dependency by itself as part of constructing the component
}
#GetMapping("/")
public String hello2(){
return this.text.hello("3");
}
}
You get this:
#RestController
public class Yono3Writer {
Yono2Writer text; // <- 1. component defines the dependency
Yono3Writer(Yono2Writer yono2Writer){
this.text = yono2Writer; // <- 2. a spring managed bean is injected using the constructor as part of constructing the component
}
#GetMapping("/")
public String hello2(){
return this.text.hello("3");
}
}
provided that you configured a bean of type Yono2Writer, one way to do that:
#Configuration
public class MyConfig {
#Bean
public Yono2Writer yono2Writer() {
return new Yono2Writer();
}
}
This is really helpful when you have a bunch of these dependencies for your component that are not all straight forward to implement unlike new Yono2Writer()

Related

Is it safe to use String as a return type of a bean in spring?

#Configuration
public class Product {
#Bean("xyz")
public String getMethod() {
return "abc";
}
}
#Component
public class Test {
String b;
Test(String xyz) {
this.b = xyz;
}
}
Is this any harm with this approach? I am trying to make change in the existing code where I am replacing the #Value with the getter as the method parameter. As I don't want to change the structure of the existing code I am trying to inject the method as bean as a replacement to #Value.
I suggest you to keep the #Value annotation instead of the whole #Bean configurations.
Why?
What if the getMethod()'s returned value needs to be changed very often? Everytime when you're changing something in the Product class, during build time it needs to be recompiled. What happens if the project is getting bigger and you're using this approach? It leads to longer build time and the more important thing is that this solution is not intuitive and it's hard to keep it clean. Don't think about complex solutions only to make the code look fancy. When you need to inject String values, the easiest approach is to create properties files (which won't get recompiled) and use the #Value annotation.
Now, if you want to add new methods without changing the structure of the existing code there are some patterns which you can apply like decorator pattern.
The main idea is simple: you're creating a decorator class which has an object of the type you need.
The easiest example (which you'll find everywhere on the internet) is the classic Shape example:
public interface Shape {
String someMethod();
}
#Component
public class CustomShape implements Shape { //implement the method here }
And here is the decorator:
public interface ShapeDecorator {
String someMethodExtended();
void someExtraMethod();
}
#Component
public class CustomShapeDecorator implements ShapeDecorator{
#Autowired
// #Qualifier - optional (only if you have more Shape implementations)
private Shape shape;
// now you can either:
// 1. provide new methods
#Override
public void someExtraMethod(){
System.out.println("Hello world!");
}
// 2. or you can EXTEND the Shape's "someMethod()" implementation
#Override
public String someMethodExtended(){
String oldString = this.shape.someMethod();
return oldString + " EXTENDED";
}
}

Decide which of multiple implementations to use in Spring Boot app

Given two (or more) implementations of a particular service API, what's the best way to pick which one to use at runtime in my app based on an application property?
Example API:
public interface Greeting {
String sayHello(String username);
}
Implementations:
public class FriendlyGreeting implements Greeting {
public String sayHello(String username) {
return "Hello, " + username;
}
}
public class HostileGreeting implements Greeting {
public String sayHello(String username) {
return "Go away, " + username;
}
}
I've got a separate service class with an #Autowired constructor that takes an instance of Greeting. What I want, is based upon a configuration property, to decide which greeting implementation gets injected and used. I came up with using a configuration class to make that decision:
#Configuration
public class GreetingConfiguration {
private String selection;
#Autowired
public GreetingConfiguration(#Value("${greeting.type}") String type) {
this.selection = type;
}
#Bean
public Greeting provideGreeting() {
if ("friendly".equals(selection)) {
return new FriendlyGreeting();
} else {
return new HostileGreeting();
}
}
}
Is this the right way to do what I want? I went down the road of using #Qualifier on the implementations, and ended up with a mess where Spring saw 3 instances of my Greeting API, and I needed a configuration anyway to pick which implementation to use and return it with a unique qualifier name on it, and that feels worse than what I settled on.
You can mark both Greeting as #Service and select the chosen one with #Qualifier("yourServiceHere") like this:
#Autowired
#Qualifier("friendlyGreeting")
private Greeting greeting;
Another way you can do it is with profile. You can mark your FriendlyGreeting service with #Service and #Profile("friendly") and the HostileGreeting service with #Service and #Profile("hostileGreeting") and just put in the application.properties the following:
spring.profiles.active=friendly
Answering my own question.
#Compass and #user268396 were correct - using Profiles got this working as expected.
I created both implementations, annotated with #Service and #Profile("friendly") or #Profile("hostile"), and could change the property spring.profiles.active to dev,friendly for example, and get what I wanted.
You can use #Conditional annotations described at https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Conditional.html and https://reflectoring.io/spring-boot-conditionals/
#Profile annotations mentioned above are based upon #Conditional(from Spring Framework); see also Spring Boot: org.springframework.boot.autoconfigure.condition
Here is a full solution using ideas mentioned by David and Vitor above with #Profile and #Qualifer annotations.
Two beans with same name but Only one is activated based on which profile is defined.
#Profile("profile1")
#Bean("greeting")
public class FriendlyGreeting implements Greeting {
---
#Profile("profile2")
#Bean("greeting")
public class HostileGreeting implements Greeting {
---
#Configuration
public class GreetingConfiguration {
private Greeting greeting;
#Autowired
public GreetingConfiguration(#Qualifier("greeting") Greeting greeting) {
this.greeting = greeting;
}
}
Notes:
you can remove the intermediate class GreetingConfiguration and stick the "greeting" bean wherever you need
i prefer the #Autowired on the constructor instead of the class member to make it easier for unit testing.

Java Spring DI not working with Java Configuration

I'm new to Java Spring and trying to use Java configuration and inject a dependency into a class constructor. I want to use constructor injection because the class methods require the dependency. It isn't working for me.
Use case: Create a JSON string from a Java object and validate it before returning.
Class: FakeJsonBuilder
Dependency: JsonValidator
Main class: Per Spring documentation the #SpringBootApplication annotation is a convenience annotation that adds #Configuration, #EnableAutoConfiguration and #ComponentScan so I should be good to go as far as dependency injection is concerned.
#SpringBootApplication
public class MySpringApplication {
public static void main(String[] args){
// Register the class we use for Java based configuration
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(ApplicationConfiguration.class);
context.refresh();
SpringApplication.run(MySpringApplication .class, args);
}
}
Java configuration class:
#Configuration
public class ApplicationConfiguration {
#Bean
public JsonValidator jsonValidator(){
return new JsonValidatorImpl();
}
#Bean
public JsonBuilder(){
return new FakeJsonBuilder();
}
}
FakeJsonBuilder class:
public class FakeJsonBuilder implements JsonBuilder{
private static Log logger = LogFactory.getLog(FakeJsonBuilder.class);
private static JsonValidator jsonValidator;
// I need an empty constructor for the ApplicationConfiguration setup to work.
public MlrModelJsonBuilder(){};
#Autowired
public FakeJsonBuilder (JsonValidator jsonValidator){
this.jsonValidator = jsonValidator;
boolean validatorInjected = (jsonValidator != null);
logger.info("Validator injected: " + validatorInjected);
}
.......... More methods
The jsonValidator dependency is not being injected, i.e. the log message is Validator injected: false
Quoting Martin: Fowler http://martinfowler.com/articles/injection.html
"My long running default with objects is as much as possible, to create valid objects at construction time. This advice goes back to Kent Beck's Smalltalk Best Practice Patterns: Constructor Method and Constructor Parameter Method. Constructors with parameters give you a clear statement of what it means to create a valid object in an obvious place. If there's more than one way to do it, create multiple constructors that show the different combinations."
I come from a .NET background and use Ninject to inject my dependencies into the class constructor for the reasons Fowler gives. I quoted Fowler because of his credibility but you will find many sources providing the same argument, i.e. if the class methods require the dependency then it should be injected into the constructor. So here's how I figured how to do it with Java Spring (I revert to my C# syntax - forgive the transgression):
The configuration class
#Configuration
public class ApplicationConfiguration {
#Bean
public IJsonValidator jsonValidator(){
return new JsonValidator();
}
#Bean
public IJsonBuilder jsonBuilder(){
return new JsonBuilder(jsonValidator());
}
}
The class into which we inject the dependency
public class JsonBuilder implements IJsonBuilder {
private static IJsonValidator _jsonValidator;
// #Autowired // not needed per Sotirios. tested and verified
public JsonBuilder(IJsonValidator jsonValidator) {
_jsonValidator = jsonValidator;
}
public String getFoobar() {
// Returns false. jsonValidator was injected
boolean foo = (_jsonValidator == null);
return "Validator was injected: " + foo;
}
... more methods

Best practice: family of classes with various type of configuration class [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am defining a family of classes used to get data from different sources (from example, a class will get data from a database, another one from a file, etc.)
Since the data sources are so different, there is no common interface for their configurations.
They all share a common method getData() though.
The idea was to define a set of predefined configurations (most of the time, the configurations used will just depend on a locale, thus there would one configuration for usa, one for france, etc.).
I have create the interface:
public interface IDataSource {
public void initialize(Object config);
public List<String> getData();
}
And the class DataSourceA:
public class DataSourceA implements IDataSource {
public void initialize(Object config) {
DataSourceAConfig configA = (DataSourceAConfig) config;
initializeA(configA);
}
public List<String> getData() {
...
}
private void initializeA(DataSourceAConfig config) {
...
}
}
and DataSourceB:
public class DataSourceB implements IDataSource {
public void initialize(Object config) {
DataSourceBConfig configB = (DataSourceBConfig) config;
initializeB(configB);
}
public List<String> getData() {
...
}
private void initializeA(DataSourceBConfig config) {
...
}
}
I am not happy with that solution (for example, using initialize(Object config), then cast the config). I am looking for advice on how to rethink the problem.
Edit:
I generated the configuration implementations using jaxb. Then the user would have to pass the type of data source and the name of the configuration file to the data source factory to get the data source.
Make an interface(abstract class) like DataSourceConfig. DataSourceAConfig and DataSourceBConfig will implement(extend) it. In your initialize method, you can replace Object with DataSourceConfig.
If your datasources are so different, you should change the IDataSource too:
public interface IDataSource<T extends DataSourceConfig> {
public void initialize(T config);
public List<String> getData();
}
DataSourceConfig will be the common interface and DataSourceB will implement IDataSource like this:
public class DataSourceB implements IDataSource<DataSourceBConfig> {
public void initialize(DataSourceBConfig config) {
initializeB(config);
}
// everything else omitted for simplicity
}

Design Pattern for one-time loaded configuration properties? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I'm often faced with the problem of storing, in memory, a few (possibly complex) configuration settings loaded from files on the filesystem. I'm wondering if there's a better way to architect a pattern to this problem, however, than what I've been using.
Essentially, my current solution involves three steps.
Build a singleton. Since data is persistent and guaranteed not to change through the runtime of the application, only one object instance should ever be needed.
When the first request for the object is made, create the object and read in from a file.
Expose data with getters.
This has the effect that a lot of my code looks like this:
MyConfiguration.getInstance().getWeightOfBomb(), which looks rather odd to me.
Is there a better way to handle this in a more semantic fashion?
Dependency Injection. You don't necessarily have to use a DI framework like Spring or Guice but you really want to avoid littering your code with singletons. You can still use a singleton in the implementation, but there is no reason the rest of your code needs to know that it is a singleton. Singletons are huge pain when unit testing and refactoring. Let your code reference an interface instead. e.g.,
interface MyConfig {
double getWeightOfBomb();
}
class SomeClass {
private MyConfig myConfig;
public void doSomething() {
myConfig.getWeightOfBomb();
}
}
class MyConfigImpl implements MyConfig {
public double getWeightOfBomb() {
return MyConfiguration.getInstance().getWeightOfBomb();
}
}
If you use a DI framework, just setup you classes to have your MyConfig implementation injected. If you don't, then the laziest approach that still has all the benefits is to do something like:
class SomeClass {
private MyConfig myConfig = new MyConfigImpl();
}
Really it's up to you. The important thing is that you can replace myConfig on a per instance basis when you later realize that you need the behavior to vary and/or for unit testing.
You could create an interface to represent the configuration:
public interface Config {
interface Key {}
String get(Key key);
String get(Key key, String defaultValue);
}
And a singleton implementation:
public enum MyConfig implements Config {
INSTANCE("/config.properties");
private final Properties config;
MyConfig(String path) {
config = new Properties();
try {
config.load(this.getClass().getResourceAsStream(path));
} catch (IOException | NullPointerException e) {
throw new ExceptionInInitializerError(e);
}
}
#Override
public String get(Config.Key key){
return config.getProperty(key.toString());
}
#Override
public String get(Config.Key key, String defaultValue) {
return config.getProperty(key.toString(), defaultValue);
}
public enum Key implements Config.Key {
PROXY_HOST("proxy.host"),
PROXY_PORT("proxy.port");
private final String name;
Key(String name) { this.name = name; }
#Override
public String toString() { return name; }
}
}
And then inject the configuration in your classes:
public class SomeClass {
private final Config config;
public SomeClass(Config config) {
this.config = config;
}
public void someMethod() {
String host = config.get(Key.PROXY_HOST);
String port = config.get(Key.PROXY_PORT, "8080");
// Do something
}
}
Additional proposal for noah's answer.
If it is inconvenient for you to write a method for each configuration parameter, then you could use enum for that. Here is what I mean:
public class Configuration {
private final Properties properties;
public enum Parameter {
MY_PARAMETER1("my.parameter1", "value1"),
MY_PARAMETER2("my.parameter2", "value2");
private final String name;
private final String defaultValue;
private Parameter(String name, String defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
private String getName() {
return name;
}
private String getDefaultValue() {
return defaultValue;
}
}
public Configuration(Properties properties) {
this.properties = (Properties)properties.clone();
}
//single method for every configuration parameter
public String get(Parameter param) {
return properties.getProperty(param.getName(), param.getDefaultValue());
}
}
After that, if you have a new configuration parameter, all you need to do is to add a new enum entry.
You can also extract an interface from Configuration class, of course, moving enum outside.

Categories

Resources