How to print the name of the files that are processed? - spring-batch

I am using MultiResourceItemReader to read multiple csv files from a directory. I would want to log the file names when the read of records from it starts. Tried the option of my Pojo implements ResourceAware & printing the resource.getFileName(). But this method gets invoked every time.
Is there a way to have the fileName only once when the read starts ?

I would extends the MultiResourceItemReader and override setResources():
#Override
void setResources(Resources resources) {
// print out using `resources`
super.setResources(resources);
}

Related

Flutter write script for to write code in project

I have a file inside my Flutter-project. A simple .dart file which looks like this:
class EnLanguage implements BaseLanguage {
#override
Map<String, String> get language => {'test': 'test'};
}
Now my goal is that I write I script which I by executing goes through all my Project-files, searches for specific Strings ( the ones with a .tr ending) and adds it to the map in the class above (key and value are the same).
I couldn't find any way to achieve this. How does a simple script looks like that can write inside my project files? Im not asking for the whole logic, I just need a start. I couldn't find anything..
Have a look at the package dcli and specifically the pack command. It does a chunk of what you need.
Not quite certain what you mean by strings ending with a .tr.
But to process each script.
var project = DartProject.self.pathToPackage;
find('*.dart', workingDirectory: project)
.forEach((script) {
read(script). forEach((line) {
If (line. contains('.tr'))
{
Extract line...
Write to generated file..
}

Can we fetch selenium test result Passed or failed in selenium Ide or selenium RC using API

Actually I am executing my selenium test by reading test case data from excel.I wanted to fetch whether the test result is Passed or failed after execution of my first test case and write it in front of test case then y second test case and write it in front of test case and so on .
Before execution of my test case excelsheet screenshoot
http://i.stack.imgur.com/L2LNz.png
after execution of my test cases excelsheet screenshoot
http://i.stack.imgur.com/mMivW.png
You can fetch the results using TestNG. TestNG contains default listeners which reads if your test passed/failed/was skipped.
To set this data in excelsheet you need to create a class that implements from ITestListener
public class ExcelListener implements ITestListener
If you use any IDE, you should see a warning about need of creating unimplemented methods. Allow system to create them and you should see methods like
#Override
public void onTestSuccess(ITestResult result) {
// TODO Auto-generated method stub
}
Then all you have to code is
1. Open excel file
2. Find the right column
3. Insert status
To do that I recommend using Java Excel API.
To read existing excelsheet you need to provide absolute path, workbook name and a sheetname. Here's my code for method getExcel
public void getExcel(String filePath, String sheetName, String fileName) throws BiffException, IOException {
String absolutePath = filePath.concat("/").concat(fileName);
file = new FileInputStream(new File(absolutePath));
workbook = Workbook.getWorkbook(file);
worksheet = workbook.getSheet(sheetName);
}
After getting an excel file, you need to iterate through data.
You can provide exact column and row.
Hope it helps!
EDIT:
Place a listener like this
#Listeners(MyExcelListener.class)
public class MyTestClass {
}

Changing working directory in Scala [duplicate]

How can I change the current working directory from within a Java program? Everything I've been able to find about the issue claims that you simply can't do it, but I can't believe that that's really the case.
I have a piece of code that opens a file using a hard-coded relative file path from the directory it's normally started in, and I just want to be able to use that code from within a different Java program without having to start it from within a particular directory. It seems like you should just be able to call System.setProperty( "user.dir", "/path/to/dir" ), but as far as I can figure out, calling that line just silently fails and does nothing.
I would understand if Java didn't allow you to do this, if it weren't for the fact that it allows you to get the current working directory, and even allows you to open files using relative file paths....
There is no reliable way to do this in pure Java. Setting the user.dir property via System.setProperty() or java -Duser.dir=... does seem to affect subsequent creations of Files, but not e.g. FileOutputStreams.
The File(String parent, String child) constructor can help if you build up your directory path separately from your file path, allowing easier swapping.
An alternative is to set up a script to run Java from a different directory, or use JNI native code as suggested below.
The relevant OpenJDK bug was closed in 2008 as "will not fix".
If you run your legacy program with ProcessBuilder, you will be able to specify its working directory.
There is a way to do this using the system property "user.dir". The key part to understand is that getAbsoluteFile() must be called (as shown below) or else relative paths will be resolved against the default "user.dir" value.
import java.io.*;
public class FileUtils
{
public static boolean setCurrentDirectory(String directory_name)
{
boolean result = false; // Boolean indicating whether directory was set
File directory; // Desired current working directory
directory = new File(directory_name).getAbsoluteFile();
if (directory.exists() || directory.mkdirs())
{
result = (System.setProperty("user.dir", directory.getAbsolutePath()) != null);
}
return result;
}
public static PrintWriter openOutputFile(String file_name)
{
PrintWriter output = null; // File to open for writing
try
{
output = new PrintWriter(new File(file_name).getAbsoluteFile());
}
catch (Exception exception) {}
return output;
}
public static void main(String[] args) throws Exception
{
FileUtils.openOutputFile("DefaultDirectoryFile.txt");
FileUtils.setCurrentDirectory("NewCurrentDirectory");
FileUtils.openOutputFile("CurrentDirectoryFile.txt");
}
}
It is possible to change the PWD, using JNA/JNI to make calls to libc. The JRuby guys have a handy java library for making POSIX calls called jnr-posix. Here's the maven info
As mentioned you can't change the CWD of the JVM but if you were to launch another process using Runtime.exec() you can use the overloaded method that lets you specify the working directory. This is not really for running your Java program in another directory but for many cases when one needs to launch another program like a Perl script for example, you can specify the working directory of that script while leaving the working dir of the JVM unchanged.
See Runtime.exec javadocs
Specifically,
public Process exec(String[] cmdarray,String[] envp, File dir) throws IOException
where dir is the working directory to run the subprocess in
If I understand correctly, a Java program starts with a copy of the current environment variables. Any changes via System.setProperty(String, String) are modifying the copy, not the original environment variables. Not that this provides a thorough reason as to why Sun chose this behavior, but perhaps it sheds a little light...
The working directory is a operating system feature (set when the process starts).
Why don't you just pass your own System property (-Dsomeprop=/my/path) and use that in your code as the parent of your File:
File f = new File ( System.getProperty("someprop"), myFilename)
The smarter/easier thing to do here is to just change your code so that instead of opening the file assuming that it exists in the current working directory (I assume you are doing something like new File("blah.txt"), just build the path to the file yourself.
Let the user pass in the base directory, read it from a config file, fall back to user.dir if the other properties can't be found, etc. But it's a whole lot easier to improve the logic in your program than it is to change how environment variables work.
I have tried to invoke
String oldDir = System.setProperty("user.dir", currdir.getAbsolutePath());
It seems to work. But
File myFile = new File("localpath.ext");
InputStream openit = new FileInputStream(myFile);
throws a FileNotFoundException though
myFile.getAbsolutePath()
shows the correct path.
I have read this. I think the problem is:
Java knows the current directory with the new setting.
But the file handling is done by the operation system. It does not know the new set current directory, unfortunately.
The solution may be:
File myFile = new File(System.getPropety("user.dir"), "localpath.ext");
It creates a file Object as absolute one with the current directory which is known by the JVM. But that code should be existing in a used class, it needs changing of reused codes.
~~~~JcHartmut
You can use
new File("relative/path").getAbsoluteFile()
after
System.setProperty("user.dir", "/some/directory")
System.setProperty("user.dir", "C:/OtherProject");
File file = new File("data/data.csv").getAbsoluteFile();
System.out.println(file.getPath());
Will print
C:\OtherProject\data\data.csv
You can change the process's actual working directory using JNI or JNA.
With JNI, you can use native functions to set the directory. The POSIX method is chdir(). On Windows, you can use SetCurrentDirectory().
With JNA, you can wrap the native functions in Java binders.
For Windows:
private static interface MyKernel32 extends Library {
public MyKernel32 INSTANCE = (MyKernel32) Native.loadLibrary("Kernel32", MyKernel32.class);
/** BOOL SetCurrentDirectory( LPCTSTR lpPathName ); */
int SetCurrentDirectoryW(char[] pathName);
}
For POSIX systems:
private interface MyCLibrary extends Library {
MyCLibrary INSTANCE = (MyCLibrary) Native.loadLibrary("c", MyCLibrary.class);
/** int chdir(const char *path); */
int chdir( String path );
}
The other possible answer to this question may depend on the reason you are opening the file. Is this a property file or a file that has some configuration related to your application?
If this is the case you may consider trying to load the file through the classpath loader, this way you can load any file Java has access to.
If you run your commands in a shell you can write something like "java -cp" and add any directories you want separated by ":" if java doesnt find something in one directory it will go try and find them in the other directories, that is what I do.
Use FileSystemView
private FileSystemView fileSystemView;
fileSystemView = FileSystemView.getFileSystemView();
currentDirectory = new File(".");
//listing currentDirectory
File[] filesAndDirs = fileSystemView.getFiles(currentDirectory, false);
fileList = new ArrayList<File>();
dirList = new ArrayList<File>();
for (File file : filesAndDirs) {
if (file.isDirectory())
dirList.add(file);
else
fileList.add(file);
}
Collections.sort(dirList);
if (!fileSystemView.isFileSystemRoot(currentDirectory))
dirList.add(0, new File(".."));
Collections.sort(fileList);
//change
currentDirectory = fileSystemView.getParentDirectory(currentDirectory);

How to write more then one class in spring batch

Situation:
I read url of file on internet from db. In itemProcessor I download this file and I want to save each row to database. Then processing continue and I want to create some new class "summary" which I want to save to db too. How should configure my job in spring batch ?
For your use-case job can be defined using this step sequence (in this way this job is also restartable):
Download file from URL to HDD using a Tasklet: a Tasklet is the strategy to process a single step; in your case something similar to this post can help and store local filename to JobExecutionContext.
Process downloaded file:
2.1. With a FlatFileItemReader<S> (or your own ItemReader/ItemStream implementation) read downloaded file
2.2 With an ItemProcessor<S,T> process each row
2.3 Write each object to processed in 2.2 to database using a custom MyWriter<T> that do summary calculation and delegate to ItemWriter<T> for T's database persistence and to ItemWriter<Summary> to write Summary object.
<S> is the bean contains each file row and
<T> is the bean your write to db
MyWriter<T> can be used in this way:
class MyWriter extends ItemWriter<T> {
private ItemWriter<Summary> summaryWriter;
private ItemWriter<T> tWriter;
public void write(List<? super T> items) {
List<Summary> summaries = new ArrayList<>(items.size());
for(T item : items) {
final Summary summary = /* Here create summary object reading from
* database or creating new object */
/* Do summary or update summary */
summaries.add(summary);
}
/* The code above is trivial: you can group Summary object using a Map<SummaryKey,Summary> to reduce reading and use summaryWriter.write(summariesMap.values()) for example */
tWriter.write(items);
summaryWriter.write(summaries);
}
}
You need to save as stream both MyWriter.summaryWriter and MyWriter.tWriter for restartability.
You can use a CompositeItemWriter.
But perhaps your summary processing should be in another step which reads the rows you previously inserted

Bulk logging using Enterprise library

Hi i am using Enterprise library 5.0 to log messages in text file, as a part of that i need to log collection of messages to the text file .
Below is the part of code which logs to text file using flatfilelistener
public void LogToFile(string message, string category, IDictionary<string, object> additionalDetail)
{
var logger = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
logger.Write(message, category, 0, 0, TraceEventType.Error, string.Empty, additionalDetail);
}
The above will log single message in text file, like that i will call for each item in collection which i need to log.
So , how to log everything in single stretch? like placing in buffer and updating logfile on single stretch.
I guess there is one property named "AutoFlush" but i don't know how to use that.
using auto flush
That is likely your best bet. Just let the buffer handle it or create a custom flush mechanism that you can call at a specified duration such as the end of a http request or if you are paranoid perhaps when an application crashes and you can't trust autoflush to work.