To test the setter dependency injection with an Array of string, I wrote the below-given code -
Pojo class is -
package com.abhishek.ioc.array;
public class Person {
private int id;
private String name;
private String[] hobbies;
public void showHobbies() {
System.out.println("Person name is - "+name+", id is - "+id);
for (int i = 0; i < hobbies.length; i++) {
System.out.println(hobbies[i]);
}
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
}
spring.xml file is -
<beans>
<bean id="person" class="com.abhishek.ioc.array.Person">
<property name="id" value="1"></property>
<property name="name" value="Abhisshek"></property>
<property name="hobbies">
<set>
<value>Playing cricket</value>
<value>Coding</value>
<value>Reading books</value>
</set>
</property>
</bean>
</beans>
Client code is -
package com.abhishek.ioc.array;
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("resources/spring.xml");
System.out.println("Creating Person object");
Person person = (Person)applicationContext.getBean("person");
System.out.println("Person object created");
person.showHobbies();
}
}
In spring.xml file, I tried tags <array>, <list> and <set> to inject data in array and all three tags are giving the correct result. How?
Related
with spring xml configuration, it is possible to define the following in app context xml to populate the status field in the TestEnum:
app context xml
<bean id="blue" class="com.example.demo.test.TestEnum" factory-method="valueOf">
<property name="status" value="${testnum.blue.status}"/>
<constructor-arg>
<value>BLUE</value>
</constructor-arg>
</bean>
<bean id="red" class="com.example.demo.test.TestEnum" factory-method="valueOf">
<property name="status" value="${testnum.red.status}"/>
<constructor-arg>
<value>RED</value>
</constructor-arg>
</bean>
enum class
public enum TestEnum {
BLUE,
RED;
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
mystatus.properties
testnum.blue.status=good
testnum.red.status=bad
Is this possible with spring boot using application.properties + java configuration without xml?
Yes, a simple environment configuration class (annotated with #ConfigurationProperties for example), will map and do the conversion of your enum automatically.
Example:
#Configuration
#Validated
#ConfigurationProperties(prefix = "my.property.path")
public class TestConfiguration{
public enum TestEnum {
BLUE, RED
}
#NotNull
private TestEnum type;
public TestConfiguration() {
}
public #NotNull TestEnum getType() {
return this.type;
}
public void setType(#NotNull TestEnum type) {
this.type = type;
}
}
I have a simple table "employee" defined as:
create table employee (id int, name varchar2(40));
I want to write an application to insert values in it and commit only after all values are inserted. Here is my code:
Employee.java:
package com.empl;
public class Employee {
private int id;
private String name;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
EmployeeDAO.java:
package com.empl;
import javax.sql.DataSource;
public interface EmployeeDAO {
public void setDataSource(DataSource dataSource);
public void create(int id, String name);
}
EmployeeJDBCTemplate.java:
package com.empl;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class EmployeeJDBCTemplate {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
public DataSource getDataSource() {
return dataSource;
}
public void create(int id, String name) {
String SQL = "insert into employee (id, name) values (?, ?)";
jdbcTemplateObject.update(SQL, id, name);
}
}
MainApp.java:
package com.empl;
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String args[]) throws SQLException {
ApplicationContext context = new
ClassPathXmlApplicationContext("Beans.xml");
EmployeeJDBCTemplate employeeJDBCTemplate =
(EmployeeJDBCTemplate) context.getBean("employeeJDBCTemplate");
employeeJDBCTemplate.getDataSource().getConnection().
setAutoCommit(false);
employeeJDBCTemplate.create(1, "E1");
employeeJDBCTemplate.create(2, "E2");
}
}
Beans.xml:
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
<bean id = "dataSource" class =
"org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name = "driverClassName" value =
"oracle.jdbc.driver.OracleDriver"></property>
<property name = "url" value =
"jdbc:oracle:thin:#localhost:1521/xe"></property>
<property name = "username" value = "sys as sysdba"></property>
<property name = "password" value = "pass"></property>
</bean>
<bean id = "employeeJDBCTemplate" class =
"com.empl.EmployeeJDBCTemplate">
<property name = "dataSource" ref = "dataSource"></property>
</bean>
</beans>
I executed the code but when I enter SQLPlus and type the rollback; command, the records are still in the table.
I saw related questions but nothing seems to work.
I would like to implement the interface at runtime based on variable.
Example :
Class A implements interface1 {
public getValue() {}
}
Class B implements interface1 {
public getValue() {}
}
So I would like to have variable sitting in configuration..., for example ClasstoImplement=A
So, if ClasstoImplement=A, then I need to call Class A.getValue()
If ClasstoImplement=B, then I need to call Class B.getValue() at runtime. And I should be able to change value of ClasstoImplement at runtime.
My application is Spring based and runs in Tomcat.
Can someone please help me to find out if there is any way??
There are many possible solutions. The one of them is to use org.springframework.aop.target.HotSwappableTargetSource.
take a look at implementation that could be considered:
public class CustomSwappable<T> implements Interface1 {
private HotSwappableTargetSource targetSource;
private String key;
private Map<String, T> swappableBeans;
#PostConstruct
private void init() {
targetSource = new HotSwappableTargetSource(swappableBeans.values().iterator().next()); // first is the default
}
// you need to track changes in config and call this method if any modifications were done
public void configChanged(String key, String value) {
if (!this.key.equals(key)) {
return;
}
if (!swappableBeans.containsKey(value)) {
return;
}
targetSource.swap(swappableBeans.get(value));
}
#Override
public String getValue() {
return ((Interface1)targetSource.getTarget()).execute();
}
#Required
public void setConfigurationKey(String key) {
this.key = key;
}
#Required
public void setSwappableBeans(Map<String, T> swappableBeans) {
this.swappableBeans = swappableBeans;
}
}
and bean declaration should as follows:
<bean id="Interface1Swappable" class="path.to.CustomSwappable">
<property name="configurationKey" value="swappableKey"/>
<property name="swappableBeans">
<util:map value-type="path.toInterface1">
<!-- first is default -->
<entry key="classA">
<bean class="path.to.class.A"/>
</entry>
<entry key="classB">
<bean class="path.to.class.B"/>
</entry>
</util:map>
</property>
</bean>
package com.nareshit.beans;
public class Address {
private String city,state;
public String toString()
{
return "\n city:"+city+"\nstate:"+state;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
package com.nareshit.clients;
import java.awt.Container;
import java.beans.Beans;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import com.nareshit.beans.Student;
public class Test {
public static void main(String[] args)
{
BeanFactory factory=new XmlBeanFactory(new ClassPathResource("MyBeans.xml"));
Student std1=(Student)factory.getBean("std");
std1.getStudentDetails();
}
}
package com.nareshit.beans;
public class Student {
private int sid;
private String name;
private String address;
public void getStudentDetails()
{
System.out.println("student id:"+sid);
System.out.println("student name:"+name);
System.out.println("student address:"+address);
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="std" class="com.nareshit.beans.Student">
<property name="std" value="1001"/>
<property name="name" value="mitu"/>
<property name="address" ref="addressObj"/>
</bean>
<bean id="addressObj" class="com.nareshit.beans.Address">
<property name="city" value="bam"/>
<property name="state" value="odisha"/>
</bean>
</beans>
This is the spring setter injection prog. where i am getting error:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'std' defined in file("")
how to solve it?
Please see com.nareshit.beans.Student class. It is having one property named as address which is a type of String. When you are writing the XML,
you are giving one reference type of com.nareshit.beans.Address.
Solution :
1. You can give a String value in the XML for address property.like
ddress property like
<bean id="std" class="com.nareshit.beans.Student">
<property name="std" value="1001"/>
<property name="name" value="mitu"/>
<property name="address" value="SOME ADDRESS"/>
</bean>
2. You can change the type of address property in Student Class like
public class Student{
Address address;
//declaration of rest property
//Some Boiler Plate Code
}
I want to autowire a String bean as below
<bean id="name" class="java.lang.String" autowire="byName">
<constructor-arg value="Aravind"/>
</bean>
<bean id="employee" class="Employee" autowire="byName"/>
public Class Employee
{
private String name;
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return name;
}
}
When I try to access the name attribute in the employee is null
Employee emp=(Employee)getApplicationContext().getBean("employee");
System.out.println(emp.getName()==null);
It prints true.
Can someone help on this?
You still need to set the property on the Employee somehow.
Setting the name can be done in multiple ways.
XML configuration.
<bean id="employee" class="Employee" autowire="byName">
<property name="name">
<ref bean="name" />
</property>
</bean>
Using #Autowired
public Class Employee {
#Autowired
private String name;
public void setName(String name) {
this.name=name;
}
public String getName() {
return name;
}
}