Spring to load the CSV file as List of Object - spring

In My Spring MVC application
I want to load CSV, like I can load properties file.
#Resource(name = "myProperties")
private Map<String, String> myProperties;
#Bean(name="myProperties")
public static PropertiesFactoryBean mapper() {
PropertiesFactoryBean bean = new PropertiesFactoryBean();
bean.setLocation(new ClassPathResource("user-form-validation-configuration.properties"));
return bean;
}
Currently I am using org.apache.commons.csv
Please let me know, if spring provide any util for csv file.
Thanks
Manu

CSV file is not a Properties file. So you cannot convert it to a Map<String, String>
You should inject the class in org.apache.commons.csv package as a Spring bean and then use it to read in your application. Or you can also try org.springframework.batch.item.file.FlatFileItemReader from Spring Batch

Related

about spring boot Profile can not work

when I use command
mvn spring-boot:run -Dspring.profiles.active=web
my project is running,but #Profile("web") bean code not used,that only use
properties which the bean write by
#Profile("default")
how can I change for it,and the properties change to web profile?
#Profile("default")
#Bean
static public PropertySourcesPlaceholderConfigurer defaultPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
Resource[] resourceLocations = new Resource[] { new ClassPathResource("job.core.properties") };
p.setLocations(resourceLocations);
return p;
}
#Profile("web")
#Bean
static public PropertySourcesPlaceholderConfigurer prodWebPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
Resource[] resourceLocations = new Resource[] {new ClassPathResource("job.core.ris.properties") };
p.setLocations(resourceLocations);
return p;
}
job.core.ris.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/job_ris?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
db.user=root
db.password=
job.core.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/dev?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
when I use action then,show this
Work with the framework not against/around it. Spring Boot has build in support to load profile specific application.properties files.
Instead of trying to shoehorn multiple PropertyPlaceholderConfigurer into a Spring Boot application. Create an application.properties and application-web.properties containing your properties.
application.properties
db.driverClass=com.mysql.jdbc.Driver
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/dev?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
application-web.properties
db.jdbcUrl=jdbc:mysql://192.168.0.68:3306/job_ris?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8
db.user=root
db.password=
(notice the missing db.driverClass you only need to include the different properties).
Next remove your custom #Bean annotated methods and let Spring Boot do the heavy lifting.
Pro Tip: Judging from the names of the properties you also have a custom #Bean for your DataSource. Instead of using custom names you probably want to use the spring.datasource.* properties and let Spring Boot create/manage your datasource.

Different yml files for different Beans in Spring

In my spring boot application, I have the main application.yml file. I have a lot of properties, and therefore I would like to have another yml files, which contains the specified properties, grouped by their logic or something.
How can I configure a Bean, to load and work all the properties from one new yml file, and another Bean from another new yml? What is the best practice for it?
I found examples using YamlPropertiesFactoryBean, and this bean can read several resources (yml files), but in an another Bean, when I autowire this YamlPropertiesFactoryBean, I cannot get that specific yml, because the getObject() of this YamlPropertiesFactoryBean will have all the yml resources I added to it.
Finally I have it! This is how it works:
I have a properties configuration class, which loads the yml files:
#Configuration
public class PropertiesConfig {
public static final String PERSONS_FILE_NAME = "persons.yml";
public static final String FOODS_FILE_NAME = "foods.yml";
#Bean
public PropertySourcesPlaceholderConfigurer properties() {
final PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
final YamlPropertiesFactoryBean personsYaml = personsPropertiesFromYamlFile();
final YamlPropertiesFactoryBean foodsYaml = foodsPropertiesFromYamlFile();
propertySourcesPlaceholderConfigurer.setPropertiesArray(personsYaml.getObject(), foodsYaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
#Bean
#Qualifier(PersonsManager.QUALIFIER_NAME)
public YamlPropertiesFactoryBean personsPropertiesFromYamlFile() {
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource(PERSONS_FILE_NAME));
return yaml;
}
#Bean
#Qualifier(FoodsManager.QUALIFIER_NAME)
public YamlPropertiesFactoryBean foodsPropertiesFromYamlFile() {
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource(FOODS_FILE_NAME));
return yaml;
}
}
And finally, I have two beans (managers), which hold only the corresponding yml properties:
#Component
public class PersonsManager extends YmlPropertiesManager {
public static final String QUALIFIER_NAME = "personsYaml";
#Autowired
public PersonsManager(#Qualifier(QUALIFIER_NAME) YamlPropertiesFactoryBean yamlObject) {
super(yamlObject);
}
...
}
and:
#Component
public class FoodsManager extends YmlPropertiesManager {
public static final String QUALIFIER_NAME = "personsYaml";
#Autowired
public FoodsManager(#Qualifier(QUALIFIER_NAME) YamlPropertiesFactoryBean yamlObject) {
super(yamlObject);
}
...
}
So the main thing here is the #Qualifier annotation.
Beans shouldn't be aware of yaml files. The yaml files are just sources that use used to build up the Spring Environment instance.
If you want specific properties for specific beans, the best way is to prefix those properties in application.yaml, and then use the #ConfigurationProperties with an argument of the prefix you want to use, to bind those properties to the bean in question.
See here:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

How to inject property values into Spring Boot component

In my Spring Boot Application, I implemented the following class with a method to call a stored procedure.
#Component
#ConfigurationProperties(prefix = "spring")
public class FmTrfUtil {
static int returnVal;
#Value("${spring.datasource.url}")
static String url;
public static int insertFmTrfs(List<String> trfs, String source) {
System.out.println(url);
EntityManager em = Persistence.createEntityManagerFactory("RIStore_FM").createEntityManager();
Session session = em.unwrap( Session.class );
final String[] trfArray = trfs.toArray(new String[trfs.size()]);
final String src = source;
session.doWork( new Work(){
public void execute(Connection conn) throws SQLException {
CallableStatement stmt = null;
OracleConnection oraCon = conn.unwrap(OracleConnection.class);
Array array = oraCon.createARRAY("VARCHAR2_TAB_T", trfArray);
stmt = conn.prepareCall("{? = call FM_TRF_UTIL.process_fm_trf(?,?)}");
stmt.registerOutParameter(1, Types.INTEGER);
stmt.setArray(2, array);
stmt.setString(3, src);
stmt.execute();
returnVal = stmt.getInt(1);
}
});
return returnVal;
}
}
Since calling stored procedure requires database connection, I need to load the these corresponding property values from application.properties:
spring.profiles.active=dev
spring.datasource.url=jdbc:oracle:thin:#ldap://xxx:389/risdev3, cn=OracleContext,dc=x,dc=net
spring.datasource.username=owner
spring.datasource.password=owner987
Based on the following articles about similar issue, Spring boot - custom variables in Application.properties and Using Spring-Boot configuration properties in your own classes and Spring Boot #ConfigurationProperties example, I added this annotation for my class #ConfigurationProperties(prefix = "spring") (properties for db connection all have "spring" as prefix). However when I run it with a test class as follows, I got error "the application must supply JDBC connection" which means properties in application.properties are not picked up.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = RistoreWebApplication.class, initializers = ConfigFileApplicationContextInitializer.class)
public class FmTrfUtilTest {
#Test
public void test() {
List<String> trfs = new ArrayList<String>();
trfs.add("TRF000001");
trfs.add("TRF000002");
int ret = FmTrfUtil.insertFmTrfs(trfs, "SARC");
assertTrue(ret > 0);
}
}
In order for #ConfigurationProperties to work, I added maven dependency spring-boot-configuration-processor too. Why is it still not working? What did I miss?
There are few things wrong here:
#Value does not work on static fields
#ConfigurationProperties are used to bind fields from application.properties or application.yml to Java object. Look at any #ConfigurationProperties annotated class from Spring Boot itself to easily understand how it should be used.
you should not use your own #ConfigurationProperties with prefix spring since it's already used by Spring Boot itself
spring-boot-configuration-processor is used only for nicer code completion in your IDE. You do not need this.
If you want to utilize Spring Boot configuration properties for database connection, instead of creating EntityManager like you do:
EntityManager em = Persistence.createEntityManagerFactory("RIStore_FM").createEntityManager();
You should just inject it assuming you have Spring Data JPA Starter in your dependency list.
I see you use lots of static methods and fields. That's not going to work with Spring. Use dependency injection instead and autowire what you need.

How do I set #Qualifier without XML in Spring 3+

I'm using the below configuration setup. The #configuration class loads the property file, and then there is an arraylist that produced which extracts the relevant chunks of the property file in a way that the classes that depend on barUserList and fooUserList can consume easily. They don't even know that it came from a property file. Huzzah for DI!
My problem comes when I try to tell Spring which one of these I want. Class Foo wants fooUserList so I should be able to use the #Qualifier annotation, but I can't find a way to /set/ the qualifier outside of XML.
So my question is this, how do I set the Qualifier for these two Spring beans in Javaland? Zero XML config is a big goal for me. I know that you can set #name and the #qualifier mechanism for Spring will default to the #name, but I'd like to avoid using that. I don't like things that "default to" other things.
I'm using Spring 3.2.5.RELEASE
#Configuration
public class AppConfig {
#Bean
Properties loadProperties() throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream("checker.properties"));
return properties;
}
#Bean
#Autowired
ArrayList<String> barUserList(Properties properties) {
ArrayList<String> barUsernames = new ArrayList<String>();
Collections.addAll(barUsernames, properties.getProperty("site.bar.watchedUsernames", "").split(","));
return barUsernames;
}
#Bean
#Autowired
ArrayList<String> fooUserList(Properties properties) {
ArrayList<String> fooUsernames = new ArrayList<String>();
Collections.addAll(fooUsernames, properties.getProperty("site.foo.watchedUsernames", "").split(","));
return fooUsernames;
}
}
One way could be by defining a name for the #Bean and using it on #Qualifier as follows:
#Bean(name="barUserList")
#Autowired
ArrayList<String> barUserList(Properties properties) {
ArrayList<String> barUsernames = new ArrayList<String>();
Collections.addAll(barUsernames, properties.getProperty("site.bar.watchedUsernames", "").split(","));
return barUsernames;
}
and within the use you could have something like:
// ...
#Autowired
#Qualifier("barUserList")
private List<String> userList;
// ...

Convert Spring bean configuration into XML configuration

i am working on BIRT reporting tool. which is need to called by spring MVC.
i got one example from spring which is here. in this example, configuration is done via bean. can anyone help me convert this configuration in to xml based configuration ?
#EnableWebMvc
#ComponentScan({ "org.eclipse.birt.spring.core","org.eclipse.birt.spring.example" })
#Configuration
public class BirtWebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/reports").setViewName("birtView");
}
#Bean
public BirtView birtView() {
BirtView bv = new BirtView();
// bv.setReportFormatRequestParameter("ReportFormat");
// bv.setReportNameRequestParameter("ReportName");
bv.setBirtEngine(this.engine().getObject());
return bv;
}
#Bean
public BeanNameViewResolver beanNameResolver() {
BeanNameViewResolver br = new BeanNameViewResolver();
return br;
}
#Bean
protected BirtEngineFactory engine() {
BirtEngineFactory factory = new BirtEngineFactory();
return factory;
}
}
I wants a similar configuration in xml file.
There's really no tool for extracting Spring annotations to Spring bean context xml file. You'll have to do it by hand, shouldn't be too hard as all the Spring annotations functionality can be duplicated into Spring context xml tags.
if you want to use spingmvc, so no need the configuration files.
my solution is that in Birt Script i call the impl java file like this :
sampleService = new Packages.com.example.warlock.service.SampleServiceImpl();
pojo = new Packages.com.example.warlock.entity.Sample();
iterator = sampleService.getSamples().iterator();
because my SampleService is a interface and SampleServiceImpl is impl java, the two java file are not config as #Bean.
At first i want to get the data from ModelMap but failed, so i skip the controller and straight to call Service, then final call the DAO to get the Data from DB

Resources