Hadoop Record Reader only reads first line then input stream seems to be closed - apache

I'm trying to implement a hadoop job, that counts how often a object (Click) appears in a dataset.
Therefore i wrote a custom file input format. The record reader seems to read only the first line of the given file and the close the input stream.
Here is the code:
The Pojo class:
package model;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableComparable;
public class Click implements WritableComparable<Click> {
private String user;
private String clickStart;
private String date;
private String clickTarget;
#Override
public void write(DataOutput out) throws IOException {
out.writeUTF(user);
out.writeUTF(clickStart);
out.writeUTF(date);
out.writeUTF(clickTarget);
}
#Override
public void readFields(DataInput in) throws IOException {
user = in.readUTF();
clickStart = in.readUTF();
date = in.readUTF();
clickTarget = in.readUTF();
}
public int compareTo(Click arg0) {
int response = clickTarget.compareTo(arg0.clickTarget);
if (response == 0) {
response = date.compareTo(arg0.date);
}
return response;
}
public String getUser(String user) {
return this.user;
}
public void setUser(String user) {
this.user = user;
}
public String getClickStart() {
return clickStart;
}
public void setClickStart(String clickStart) {
this.clickStart = clickStart;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getClickTarget() {
return clickTarget;
}
public void setClickTarget(String clickTarget) {
this.clickTarget = clickTarget;
}
public String toString() {
return clickStart + "\t" + date;
}
}
Here is the FileInputFormat class:
package ClickAnalysis;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import model.Click;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.util.StringUtils;
import org.apache.tools.ant.types.CommandlineJava.SysProperties;
public class ClickAnalysisInputFormat extends FileInputFormat<Click, IntWritable>{
#Override
public RecordReader<Click, IntWritable> createRecordReader(
InputSplit split, TaskAttemptContext context) throws IOException,
InterruptedException {
System.out.println("Creating Record Reader");
return new ClickReader();
}
public static class ClickReader extends RecordReader<Click, IntWritable> {
private BufferedReader in;
private Click key;
private IntWritable value;
#Override
public void initialize(InputSplit inputSplit, TaskAttemptContext context) throws IOException, InterruptedException {
key = new Click();
value = new IntWritable(1);
System.out.println("Starting to read ...");
FileSplit split = (FileSplit) inputSplit;
Configuration conf = context.getConfiguration();
Path path = split.getPath();
InputStream is = path.getFileSystem(conf).open(path);
in = new BufferedReader(new InputStreamReader(is));
}
#Override
public boolean nextKeyValue() throws IOException, InterruptedException {
String line = in.readLine();
System.out.println("line: " + line);
boolean hasNextKeyValue;
if (line == null) {
System.out.println("line is null");
hasNextKeyValue = false;
} else {
String[] click = StringUtils.split(line, '\\', ';');
System.out.println(click[0].toString());
System.out.println(click[1].toString());
System.out.println(click[2].toString());
key.setClickStart(click[0].toString());
key.setDate(click[1].toString());
key.setClickTarget(click[2].toString());
value.set(1);
System.out.println("done with first line");
hasNextKeyValue = true;
}
System.out.println(hasNextKeyValue);
return hasNextKeyValue;
}
#Override
public Click getCurrentKey() throws IOException, InterruptedException {
return this.key;
}
#Override
public IntWritable getCurrentValue() throws IOException, InterruptedException {
return this.value;
}
#Override
public float getProgress() throws IOException, InterruptedException {
return 0;
}
public void close() throws IOException {
in.close();
System.out.println("in closed");
}
}
}
The Mapper class:
package ClickAnalysis;
import java.io.IOException;
import model.Click;
import model.ClickStartTarget;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Mapper;
import org.jruby.RubyProcess.Sys;
public class ClickAnalysisMapper extends Mapper<Click, IntWritable, Click, IntWritable> {
private static final IntWritable outputValue = new IntWritable();
#Override
protected void map(Click key, IntWritable value, Context context) throws IOException, InterruptedException {
System.out.println("Key: " + key.getClickStart() + " " + key.getDate() + " " + key.getClickTarget() + " Value: " + value);
outputValue.set(value.get());
System.out.println(outputValue.get());
context.write(key, outputValue);
System.out.println("nach context");
}
}
Partitioner class:
package ClickAnalysis;
import model.Click;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Partitioner;
public class ClickAnalysisPartitioner extends Partitioner<Click, IntWritable> {
#Override
public int getPartition(Click key, IntWritable value, int numPartitions) {
System.out.println("in Partitioner drinnen");
int partition = numPartitions;
return partition;
}
}
Hadoop Job, which is triggered via an Restful web service call in a servlet container, but this shouldn't be the problem:
package ClickAnalysis;
import model.Click;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
public class ClickAnalysisJob {
public int run() throws Exception {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "ClickAnalysisJob");
job.setJarByClass(ClickAnalysisJob.class);
// Job Input path
FileInputFormat.setInputPaths(job, "hdfs://localhost:9000/user/hadoop/testdata1.csv");
// Job Output path
Path out = new Path("hdfs://localhost:9000/user/hadoop/clickdataAnalysis_out");
FileOutputFormat.setOutputPath(job, out);
out.getFileSystem(conf).delete(out,true);
job.setMapperClass(ClickAnalysisMapper.class);
job.setReducerClass(Reducer.class);
job.setPartitionerClass(ClickAnalysisPartitioner.class);
//job.setReducerClass(ClickAnalysisReducer.class);
job.setInputFormatClass(ClickAnalysisInputFormat.class);
job.setOutputFormatClass(SequenceFileOutputFormat.class);
job.setOutputKeyClass(Click.class);
job.setOutputValueClass(IntWritable.class);
job.setMapOutputKeyClass(Click.class);
job.setMapOutputValueClass(IntWritable.class);
System.out.println("in run drinnen");
//job.setGroupingComparatorClass(ClickTargetAnalysisComparator.class);
job.setNumReduceTasks(1);
int result = job.waitForCompletion(true)? 0:1;
return result;
}
}
Next the dataset (example):
/web/big-data-test-site/test-seite-1;2014-07-08;ein ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein anderes ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein anderes ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein drittes ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein viertes ziel
/web/big-data-test-site/test-seite-1;2014-07-08;ein ziel
When I run the program the syso's are showing following:
in run drinnen
Creating Record Reader
Starting to read ...
line: /web/big-data-test-site/test-seite-1;2014-07-08;ein ziel
/web/big-data-test-site/test-seite-1
2014-07-08
ein ziel
done with first line
true
Key: /web/big-data-test-site/test-seite-1 2014-07-08 ein ziel Value: 1
1
in closed
analyze Method: 1
From that i conclude that the record reader only reads the first line.
Why is this happening and how is it fixed?

Related

How to solve this issue about Java DB connection

There are my codes.
MemberDAO.java
package sec05.ex01;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class MemberDAO {
PreparedStatement pstmt;
Connection connection;
public List<MemberVO> listMembers() {
List<MemberVO> list = new ArrayList<>();
try {
connDB();
String query = "SELECT * FROM t_member";
System.out.println("preparedStatement: " + query);
pstmt = connection.prepareStatement(query);
ResultSet rs = pstmt.executeQuery(query);
while (rs.next()) {
String id = rs.getString("id");
String pwd = rs.getString("pwd");
String name = rs.getString("name");
String email = rs.getString("email");
Date joinDate = rs.getDate("joinDate");
MemberVO vo = new MemberVO();
vo.setId(id);
vo.setPwd(pwd);
vo.setName(name);
vo.setEmail(email);
vo.setJoinDate(joinDate);
list.add(vo);
}
rs.close();
pstmt.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
private void connDB() {
try {
String url = "jdbc:oracle:thin:#localhost:1521:XE";
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("Loaded Oracle Driver");
connection = DriverManager.getConnection(url, "system", "oracle");
System.out.println("Connection created.");
System.out.println("PreparedStatement created.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
MemberServlet.java
package sec05.ex01;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Date;
import java.util.List;
#WebServlet("/member")
public class MemberServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
MemberDAO dao = new MemberDAO();
List<MemberVO> list = dao.listMembers();
out.print("<html><body>");
out.print("<table border=1><tr align='center' bgcolor='lightgreen'>");
out.print("<td>ID</td><td>PWD</td><td>NAME</td><td>EMAIL</td><td>DATE</td></tr>");
for (MemberVO memberVO : list) {
String id = memberVO.getId();
String pwd = memberVO.getPwd();
String name = memberVO.getName();
String email = memberVO.getEmail();
Date joinDate = memberVO.getJoinDate();
out.print("<tr><td" + id + "</td><td>" + pwd + "</td><td>" + name + "</td><td>" + email + "</td><td>" + joinDate + "</td></tr>");
}
out.print("</table></body></html>");
}
}
MemberVO.java
package sec05.ex01;
import java.sql.Date;
public class MemberVO {
private String id;
private String pwd;
private String name;
private String email;
private Date joinDate;
public MemberVO() {
System.out.println("MemberVO constructor called.");
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getJoinDate() {
return joinDate;
}
public void setJoinDate(Date joinDate) {
this.joinDate = joinDate;
}
}
Error Message
But when I use console in IntelliJ, it works.
Database console in IntelliJ
Also, I added a jdbc library. (I'm using jdk17)
IntelliJ Library
I tried to change the library version to 8.
The ClassNotFoundException and NullPointerException occured.

Jackson-Serialiser: Ignore Field at Serialisation Time

My situation asks for a bit more complex serialisation. I have a class Available (this is a very simplified snippet):
public class Available<T> {
private T value;
private boolean available;
...
}
So a POJO
class Tmp {
private Available<Integer> myInt = Available.of(123);
private Available<Integer> otherInt = Available.clean();
...
}
would normally result in
{"myInt":{available:true,value:123},"otherInt":{available:false,value:null}}
However, I want a serialiser to render the same POJO like this:
{"myInt":123}
What I have now:
public class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> available, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException {
if (available != null && available.isAvailable()) {
jsonGenerator.writeObject(available.getValue());
}
// MISSING: nothing at all should be rendered here for the field
}
#Override
public Class<Available<?>> handledType() {
#SuppressWarnings({ "unchecked", "rawtypes" })
Class<Available<?>> clazz = (Class) Available.class;
return clazz;
}
}
A test
#Test
public void testSerialize() throws Exception {
SimpleModule module = new SimpleModule().addSerializer(new AvailableSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
outputs
{"myInt":123,"otherInt"}
Can anyone tell me how to do the "MISSING"-stuff? Or if I'm doing it all wrong, how do I do it then?
The restriction I have is that I don't want the developers to add #Json...-annotations all the time to fields of type Available. So the Tmp-class above is an example of what a typical using class should look like. If that's possible...
Include.NON_DEFAULT
If we assume that your clean method is implemented in this way:
class Available<T> {
public static final Available<Object> EMPTY = clean();
//....
#SuppressWarnings("unchecked")
static <T> Available<T> clean() {
return (Available<T>) EMPTY;
}
}
You can set serialisation inclusion to JsonInclude.Include.NON_DEFAULT value and it should skip values set to EMPTY (default) values. See below example:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import java.io.IOException;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(new AvailableSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
}
class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeObject(value.getValue());
}
#Override
#SuppressWarnings({"unchecked", "rawtypes"})
public Class<Available<?>> handledType() {
return (Class) Available.class;
}
}
Above code prints:
{"myInt":123}
Custom BeanPropertyWriter
If you do not want to use Include.NON_DEFAULT you can write your custom BeanPropertyWriter and skip all values you want. See below example:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(new AvailableSerializer());
module.setSerializerModifier(new BeanSerializerModifier() {
#Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
List<BeanPropertyWriter> writers = new ArrayList<>(beanProperties.size());
for (BeanPropertyWriter writer : beanProperties) {
if (writer.getType().getRawClass() == Available.class) {
writer = new SkipNotAvailableBeanPropertyWriter(writer);
}
writers.add(writer);
}
return writers;
}
});
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
}
class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeObject(value.getValue());
}
#Override
#SuppressWarnings({"unchecked", "rawtypes"})
public Class<Available<?>> handledType() {
return (Class) Available.class;
}
}
class SkipNotAvailableBeanPropertyWriter extends BeanPropertyWriter {
SkipNotAvailableBeanPropertyWriter(BeanPropertyWriter base) {
super(base);
}
#Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
// copier from super.serializeAsField(bean, gen, prov);
final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null);
if (value == null || value instanceof Available && !((Available) value).isAvailable()) {
return;
}
super.serializeAsField(bean, gen, prov);
}
}
Above code prints:
{"myInt":123}
After Michał Ziober's answer I had to look for something regarding Include.NON_DEFAULT and the default object and ran into this answer explaining Include.NON_EMPTY that Google didn't return in my first research (thanks Google).
So things become easier, it's now:
public class AvailableSerializer extends JsonSerializer<Available<?>> {
#Override
public void serialize(Available<?> available, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException {
jsonGenerator.writeObject(available.getValue());
}
#Override
public Class<Available<?>> handledType() {
#SuppressWarnings({ "unchecked", "rawtypes" })
Class<Available<?>> clazz = (Class) Available.class;
return clazz;
}
#Override
public boolean isEmpty(SerializerProvider provider, Available<?> value) {
return value == null || !value.isAvailable();
}
}
with the test
#Test
public void testSerialize() throws Exception {
SimpleModule module = new SimpleModule().addSerializer(availableSerializer);
objectMapper.registerModule(module);
objectMapper.configOverride(Available.class).setInclude(
// the call comes from JavaDoc of objectMapper.setSerializationInclusion(...)
JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY, JsonInclude.Include.ALWAYS));
Tmp tmp = new Tmp();
assertThat(objectMapper.writeValueAsString(tmp)).isEqualTo("{\"myInt\":123}");
tmp.otherInt.setValue(123);
assertThat(objectMapper.writeValueAsString(tmp)).isEqualTo("{\"myInt\":123,\"otherInt\":123}");
}
So please, if you upvote my answer please also upvote Michał Ziober's as that's also working with a mildly different approach.

How to format SimpleIntegerProperty output

I do have a SimpleIntegerProperty which contains a number which is the time in 100ms steps like 40 is 4,0 seconds
I do want to display this value to the user with a Label which should display "4,0 s"
I would like to bind the value with the bindings api like
label.textProperty().bind(myobject.secondsProperty().asString());
but how do i create a simple and reusable Converter, i do need only the unidirectional binding.
There is an overloaded form of the asString(...) method that takes a format string as an argument:
String secondsFormat = "%.1f s" ;
label.textProperty().bind(myobject.secondsProperty().asString(secondsFormat));
If you really need a StringConverter, you can do
StringConverter<Integer> deciSecondsConverter = new StringConverter<Integer>() {
#Override
public String toString(Integer deciSeconds) {
return String.format("%.1f s", deciSeconds.doubleValue()/10);
}
#Override
public Integer fromString(String string) {
// not implemented
return null ;
}
};
and then
label.textProperty().bind(Bindings.createStringBinding(
() -> deciSecondsConverter.toString(myobject.getSeconds()),
myobject.secondsProperty()
));
SSCCE:
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class StopwatchTest extends Application {
#Override
public void start(Stage primaryStage) {
IntegerProperty tenthsOfSeconds = new SimpleIntegerProperty();
Label label = new Label();
StringConverter<Integer> deciSecondsConverter = new StringConverter<Integer>() {
#Override
public String toString(Integer deciSeconds) {
return String.format("%.1f s", deciSeconds.doubleValue()/10);
}
#Override
public Integer fromString(String string) {
// not implemented
return null ;
}
};
label.textProperty().bind(Bindings.createStringBinding(() ->
deciSecondsConverter.toString(tenthsOfSeconds.get()),
tenthsOfSeconds));
new AnimationTimer() {
#Override
public void handle(long now) {
tenthsOfSeconds.set((int)System.currentTimeMillis() % 60000 / 100);
}
}.start();
label.setPadding(new Insets(5, 20, 5, 20));
primaryStage.setScene(new Scene(label, 80, 30));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Include TestNG to hybrid selenium framework

I have the below code in driverscript. I need to embed TestNG to it. How can I do this? ActionKeywords.java is defining all the action keywords.
Where should I give the TestNG annotation?
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;
import org.apache.log4j.xml.DOMConfigurator;
import config.ActionKeywords;
import config.Constants;
import utility.ExcelUtils;
import utility.Log;
public class DriverScript {
public static Properties OR;
public static ActionKeywords actionKeywords;
public static String sActionKeyword;
public static String sPageObject;
public static Method method[];
public static int iTestStep;
public static int iTestLastStep;
public static String sTestCaseID;
public static String sRunMode;
public static String sData;
public static boolean bResult;
public DriverScript() throws NoSuchMethodException, SecurityException{
actionKeywords = new ActionKeywords();
method = actionKeywords.getClass().getMethods();
}
public static void main(String[] args) throws Exception {
ExcelUtils.setExcelFile(Constants.Path_TestData);
DOMConfigurator.configure("log4j.xml");
String Path_OR = Constants.Path_OR;
FileInputStream fs = new FileInputStream(Path_OR);
OR= new Properties(System.getProperties());
OR.load(fs);
DriverScript startEngine = new DriverScript();
startEngine.execute_TestCase();
}
private void execute_TestCase() throws Exception {
int iTotalTestCases = ExcelUtils.getRowCount(Constants.Sheet_TestCases);
System.out.println("Total TC count" + iTotalTestCases);
for(int iTestcase=1;iTestcase<iTotalTestCases;iTestcase++){
bResult = true;
sTestCaseID = ExcelUtils.getCellData(iTestcase, Constants.Col_TestCaseID, Constants.Sheet_TestCases);
sRunMode = ExcelUtils.getCellData(iTestcase, Constants.Col_RunMode,Constants.Sheet_TestCases);
if (sRunMode.equals("Yes")){
Log.startTestCase(sTestCaseID);
iTestStep = ExcelUtils.getRowContains(sTestCaseID, Constants.Col_TestCaseID, Constants.Sheet_TestSteps);
iTestLastStep = ExcelUtils.getTestStepsCount(Constants.Sheet_TestSteps, sTestCaseID, iTestStep);
bResult=true;
for (;iTestStep<iTestLastStep;iTestStep++){
sActionKeyword = ExcelUtils.getCellData(iTestStep, Constants.Col_ActionKeyword,Constants.Sheet_TestSteps);
sPageObject = ExcelUtils.getCellData(iTestStep, Constants.Col_PageObject, Constants.Sheet_TestSteps);
sData = ExcelUtils.getCellData(iTestStep, Constants.Col_DataSet, Constants.Sheet_TestSteps);
execute_Actions();
if(bResult==false){
ExcelUtils.setCellData(Constants.KEYWORD_FAIL,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
Log.endTestCase(sTestCaseID);
break;
}
}
if(bResult==true){
ExcelUtils.setCellData(Constants.KEYWORD_PASS,iTestcase,Constants.Col_Result,Constants.Sheet_TestCases);
Log.endTestCase(sTestCaseID);
}
}
}
}
private static void execute_Actions() throws Exception {
for(int i=0;i<method.length;i++){
if(method[i].getName().equals(sActionKeyword)){
method[i].invoke(actionKeywords,sPageObject, sData);
if(bResult==true){
ExcelUtils.setCellData(Constants.KEYWORD_PASS, iTestStep, Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
break;
}else{
ExcelUtils.setCellData(Constants.KEYWORD_FAIL, iTestStep, Constants.Col_TestStepResult, Constants.Sheet_TestSteps);
ActionKeywords.closeBrowser("","");
break;
}
}
}
}
}

Unable to log in to Apache FTP Server

I am trying to integrate the Apache FTP server into my application. I have followed the instructions given here but have run into some problems. Currently I am able to run the server and connect to it from my browser but can not log in. I have tried admin/admin and anonymous/*, but the login fails every time. In the apache-ftpserver-1.0.6 source code I had downloaded, the files associated with the user manager are located in res/conf, although when I try to match that file path in my own program I get an error that says "invalid resource directory name" and am unable to build. I also tried including the files users.properties and ftpd-typical.xml in the main directly and can run, but again cannot log in. It seems like my project does not realize these files are present.
Does anyone have experience with Apache FTP Server that could tell me the correct way to include these files so that I can log in to my server?
Thanks!
P.S. I don't think it should make any difference, but I am developing this program for Android.
In the following code I am crating admin user and non-admin user, setting restrictions of reading, writing and restricting throttling and upload rate limit and imposing download rate limiting.
Added a listener to listen user login and logout download start and download finish events.
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FileSystemFactory;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.ftpletcontainer.impl.DefaultFtpletContainer;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.ConcurrentLoginPermission;
import org.apache.ftpserver.usermanager.impl.TransferRatePermission;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SFTPServer {
// ===========================================================
// Constants
// ===========================================================
private final int FTP_PORT = 2221;
private final String DEFAULT_LISTENER = "default";
// private final Logger LOG = LoggerFactory.getLogger(SFTPServer.class);
private static final List<Authority> ADMIN_AUTHORITIES;
private static final int BYTES_PER_KB = 1024;
private static final String DEFAULT_USER_DIR = "C:\\upload";
public final static int MAX_CONCURRENT_LOGINS = 1;
public final static int MAX_CONCURRENT_LOGINS_PER_IP = 1;
// ===========================================================
// Fields
// ===========================================================
private static FtpServer mFTPServer;
private static UserManager mUserManager;
private static FtpServerFactory mFTPServerFactory;
private ListenerFactory mListenerFactor;
// ===========================================================
// Constructors
// ===========================================================
static {
// Admin Authorities
ADMIN_AUTHORITIES = new ArrayList<Authority>();
ADMIN_AUTHORITIES.add(new WritePermission());
ADMIN_AUTHORITIES.add(new ConcurrentLoginPermission(MAX_CONCURRENT_LOGINS, MAX_CONCURRENT_LOGINS_PER_IP));
ADMIN_AUTHORITIES.add(new TransferRatePermission(Integer.MAX_VALUE, Integer.MAX_VALUE));
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public void init() throws FtpException {
mFTPServerFactory = new FtpServerFactory();
mListenerFactor = new ListenerFactory();
mListenerFactor.setPort(FTP_PORT);
mFTPServerFactory.addListener(DEFAULT_LISTENER, mListenerFactor.createListener());
mFTPServerFactory.getFtplets().put(FTPLetImpl.class.getName(), new FTPLetImpl());
PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
userManagerFactory.setFile(new File("ftpusers.properties"));
userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
mUserManager = userManagerFactory.createUserManager();
mFTPServerFactory.setUserManager(mUserManager);
this.createAdminUser();
SFTPServer.addUser("admin1", "admin1", 20, 20);
mFTPServer = mFTPServerFactory.createServer();
mFTPServer.start();
}
private UserManager createAdminUser() throws FtpException {
UserManager userManager = mFTPServerFactory.getUserManager();
String adminName = userManager.getAdminName();
if (!userManager.doesExist(adminName)) {
// LOG.info((new
// StringBuilder()).append("Creating user : ").append(adminName).toString());
BaseUser adminUser = new BaseUser();
adminUser.setName(adminName);
adminUser.setPassword(adminName);
adminUser.setEnabled(true);
adminUser.setAuthorities(ADMIN_AUTHORITIES);
adminUser.setHomeDirectory(DEFAULT_USER_DIR);
adminUser.setMaxIdleTime(0);
userManager.save(adminUser);
}
return userManager;
}
public static void addUser(String username, String password, int uploadRateKB, int downloadRateKB) throws FtpException {
BaseUser user = new BaseUser();
user.setName(username);
user.setPassword(password);
user.setHomeDirectory(DEFAULT_USER_DIR);
user.setEnabled(true);
List<Authority> list = new ArrayList<Authority>();
list.add(new TransferRatePermission(downloadRateKB * BYTES_PER_KB, uploadRateKB * BYTES_PER_KB)); // 20KB
list.add(new ConcurrentLoginPermission(MAX_CONCURRENT_LOGINS, MAX_CONCURRENT_LOGINS_PER_IP));
user.setAuthorities(list);
mFTPServerFactory.getUserManager().save(user);
}
public static void restartFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.stop();
try {
Thread.sleep(1000 * 3);
} catch (InterruptedException e) {
}
mFTPServer.start();
}
}
public static void stopFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.stop();
}
}
public static void pauseFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.suspend();
}
}
public static void resumeFTP() throws FtpException {
if (mFTPServer != null) {
mFTPServer.resume();
}
}
public static void main(String... are) {
try {
new SFTPServer().init();
} catch (FtpException e) {
e.printStackTrace();
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
FTPLET Listener
import java.io.IOException;
import org.apache.ftpserver.ftplet.DefaultFtplet;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.FtpletResult;
public class FTPLetImpl extends DefaultFtplet {
#Override
public FtpletResult onLogin(FtpSession session, FtpRequest request) throws FtpException, IOException {
System.out.println(session.getUser().getName() + " Logged in");
return super.onLogin(session, request);
}
#Override
public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException {
System.out.println(session.getUser().getName() + " Disconnected");
return super.onDisconnect(session);
}
#Override
public FtpletResult onDownloadStart(FtpSession session, FtpRequest request) throws FtpException, IOException {
System.out.println(session.getUser().getName() + " Started Downloading File " + request.getArgument());
return super.onDownloadStart(session, request);
}
#Override
public FtpletResult onDownloadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
System.out.println("Finished Downloading " + request.getArgument());
return super.onDownloadEnd(session, request);
}
}