Spring Batch: How to set the first line columns (header), of the csv file to token name for my file reader - spring-integration

I have a csv file to consume through spring batch. The column header (names) can differ based on the customer. When reading the data using FlatFileItemReader, how would i set the token name(s) to be the first line (header) column name(s) ? I am using Java Configuration to setup the flow.
Appreciate any comments/suggestions

One solution could be to discard the first line of the csv files with the FlatFileItemReader::setLinesToSkip method. Such as :
flatFileItemReader.setLinesToSkip(1);

You should set LineToSkip Property :
#Component
#JobScope
public class CsvToDbItemReader extends FlatFileItemReader<BillDTO> {
public CsvToDbItemReader(#Value("#{jobParameters}") Map jobParameters)
{
String uploadDate = (String) jobParameters.get("uploadDate");
this.setResource(new FileSystemResource(getFileName(uploadDate)));
this.setLinesToSkip(1); //set header line
LineMapper<BillDTO> lineMapper = createBillLineMapper();
this.setLineMapper(lineMapper);
}
}

You can use as below:
<bean id="flatFileItemReader"
class="org.springframework.batch.item.file.FlatFileItemReader">
<!-- linesToSkip => The number of lines to skip at the beginning of the
file. This feature is particularly useful to handle file headers. -->
<property name="linesToSkip" value="1" />

Related

Does AllowedFileTypes in UploadDialog allow for multiple file types, and if so, what is the format?

If I just set one file type, it'll filter properly and allow for the image to be uploaded.
If I try multiple file types in the property, it may filter them, but it will always error (screen shots below). I've tried inputting the two types I want as "png, jpg", "png jpg", "pngjpg", and ".png, .jpg", but none of them work. Some of the formats will auto set the filter to show both *.png, *.jpg, but when I select the file I get an error. Can this work with multiple file types?
Setting field values:
Showing images:
Error on selecting image:
Did you try semi-colon ; separator?
This is the standard Windows extension separator and there's indication Acumatica uses this character for parsing.
/// <summary>
/// Gets or sets string representing file types which are allowed for selecting.
/// </summary>
[Category("Behavior")]
[Description("The string that lists the file types that are allowed for selecting.")]
public string AllowedFileTypes
{
get
{
return this.allowedFileTypes;
}
set
{
this.allowedFileTypes = "";
if (string.IsNullOrEmpty(value))
return;
this.SetAllowedFileTypes(value.Split(';'));
}
}

ReplyRequiredException on attempt to get data from <int-jdbc:outbound-gateway>?

I would like to define an
<int-jdbc:outbound-gateway/> with query and without update to retrieve data from database. Then I would like to use the int-jdbc:outbound-gateway as an implementation of Service.findSomeData() interface method. The data retrieved from interface implementation is used in my custom transformer's CheckService class. See the configuration below:
<int:service-activator method=“performCheck”>
<bean class=“com.example.service.CheckService”
c:service-ref=“service”
</int:service-activator>
<int:gateway id=“service” service-interface=“com.example.service.Service”>
<int:method name=“findSomeData” request-channel=“jdbcChan” reply-channel=“jdbcChanReply”/>
</int:gateway>
<int-jdbc:outbound-gateway request-channel=“jdbcChan”
data-source=“pooledDs” row-mapper=“dataRowMapper” reply-channel=“jdbcChanReply”>
<int-jdbc:query>
select some, data from some_table
</int-jdbc:query>
The problem is that I get ReplyRequiredException exception when I move my payload to jdbcChan:
org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'org.springframework.integration.jdbc.JdbcOutboundGateway#0', and its 'requiresReply' property is set to true.
I decided to pay more attention on example located in spring in spring-integration-samples repository on GitHub, but looks like it also does not work as expected. I get exactly the same exception in example project trying to find User by name foo. You can easily reproduce the exception with basic jdbc example located on GitHub and the following test method:
#Test
public void findPerson() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"/META-INF/spring/integration/spring-integration-context.xml");
PersonService service = context.getBean(PersonService.class);
final List<Person> foo = service.findPersonByName("foo");
assertThat(foo, is(not(empty())));
}
Am I doing it wrong or there is a bug in latest Spring Integration JDBC? (for me looks like even example is broken)
I fixed the sample.
We changed the default for requires-reply to true a long time ago but the sample was never updated.
assertThat(foo, is(not(empty())));
However, the List<Person> is null when no results are received.
EDIT
But I would expect empty list instead of a null if ResultSet was empty.
That's not how it works.
If the resultSet is empty, null is returned (hence the original error you were seeing).
If the resultSet has 1 entry, just that entry is returned.
Otherwise a list of entities is returned.
Object payload = list;
if (list.isEmpty()) {
return null;
}
if (list.size() == 1) {
payload = list.get(0);
}
return payload;
It's been like that forever but I believe the single Object Vs. List is wrong (if maxRows > 1).
maxRows is 1 by default so it made sense then; however, if maxRows is > 1 and only 1 row is returned I think it should still be a list of 1. The application shouldn't have to check the type of the result. It either expects a list or a single object (or null). INT-4559.

SOAPUI Load Custom Properties from file using groovy

I am trying to write a groovy script which loads the custom properties for a test suite using information from a properties file.
The properties file has around 6 different attributes
I have had a look at quite a few different methods i.e Loading from Properties test step and trying to expand the properties with groovy, but have not been successful.
If anyone could advise on how to achieve this, it would be much appreciated.
Thanks in advance.
Here is the groovy script which reads a property file and set them at test suite level:
def props = new Properties()
//replace the path with your file name below. use / instead of \ as path separator even on windows platform.
new File("/absolute/path/of/test.properties").withInputStream { s ->
props.load(s)
}
props.each {
context.testCase.testSuite.setPropertyValue(it.key, it.value)
}
The above script load test suite level for the current suite where the groovy script is present.
Unfortunately, in my case I want to have the properties in the same order as the input file, ie. sorted, and this methode does not work.
I wanted to load a 'Project properties' file containing sorted properties and each time I used this method it stored them unsorted.
I had to use a more straightforward method (see below). If anyone knows about a more elegant/practical way to do it, I'm interested
def filename = context.expand( '${#TestCase#filename}' )
def propertiesFile = new File(filename)
assert propertiesFile.exists(), "$filename does not exist"
project = testRunner.testCase.testSuite.project
//Remove properties
project.propertyNames.collect{project.removeProperty(it)}
//load the properties of external file
propertiesFile.eachLine {
line->
firstIndexOf = line.indexOf('=') // properties as set as key=value in the file
key = line.substring(0, firstIndexOf)
value = line.substring(firstIndexOf+1)
project.setPropertyValue(key, value)
}

Change dynamical directory on file:inbound-channel-adapter

I'm new with Spring and I'm using Citrus Framework.
I'll try to change, dynamically, the inbound-channel-adapter destination variable. This variable is located in properties file and change all the time.
Currently I'm using an AtomicReference and I change its value in java code
In context.xml :
<bean id="targetDir" class="java.util.concurrent.atomic.AtomicReference">
<constructor-arg value="${output.path.temp}"/>
</bean>
<file:inbound-channel-adapter id="fileInboundAdapter" auto-create-directory="false"
channel="fileChannel" directory="file:#targetDir.get()" auto-startup="false"
filename-pattern="*.xml">
<si:poller cron="0 * * * * ?"/>
</file:inbound-channel-adapter>
And in java file :
SourcePollingChannelAdapter fileInboundAdapter = (SourcePollingChannelAdapter)context.getApplicationContext().getBean("fileInboundAdapter");
if (fileInboundAdapter.isRunning()) {
fileInboundAdapter.stop();
#SuppressWarnings("unchecked")
AtomicReference<String> targetDir = (AtomicReference<String>)
context.getApplicationContext().getBean("targetDir", AtomicReference.class);
targetDir.set(strOutPath[0]+"/"+strOutPath[1]+"/"+strOutPath[2]+"/"+strOutPath[3]+"/");
fileInboundAdapter.start();
}
This solution don't works ... someone have any solutions ?
Thanks a lot.
That's true. Because your AtomicReference doesn't have affect to the target directory.
You do this directory="file:#targetDir.get()". It isn't correct at all, because this String will try to be converted to the File object. If you want to use here a SpEL it should be like this:
directory="#{targetDir.get()}"
without any file: prefix.
Anyway it doesn't help because that SpEL is evaluated only once at applicationContext strtup.
Since you are going to change the directory at runtime you should use FileReadingMessageSource.setDirectory from your service. Something like this:
SourcePollingChannelAdapter fileInboundAdapter = (SourcePollingChannelAdapter)context.getApplicationContext().getBean("fileInboundAdapter");
if (fileInboundAdapter.isRunning())
fileInboundAdapter.stop();
FileReadingMessageSource source = (FileReadingMessageSource) context.getApplicationContext().getBean("fileInboundAdapter.source");
source.setDirectory(new File(strOutPath[0]+"/"+strOutPath[1]+"/"+strOutPath[2]+"/"+strOutPath[3]+"/"));
fileInboundAdapter.start();
}
And get rid of that AtomicReference.
From the start you can use property-placeholder for the directory attribute directly.

How to passe table/view entity as a parameter

consider the following code , this is a method in my BLL to extract data from my DAL which is an EF4 .edmx file
public ObservableCollection<Glass> ShowGlasses()
...
var result = from d in glassContext.GLASSes
...
now I want to replace glassContext.GLASSes with a parameter so that I can access different tables/views with the same structure using this method, for example I may want to use glassContext.GLASSes2 instead, how can I do this ?
Thanks in advance
I think you want something like this
public ObservableCollection<T> ShowGlasses<T>(ObjectQuery<T> source)
{
...
var result = from d in source
...
}

Resources