I've a Java program that is copying a file from Unix to hdfs. It is running fine however I am looking for impersonating a different account when it runs and copies file.
Input: Apart form input file and target hdfs directory path, another input should be properties file containing account, keytab directory, domain
Please kindly let me know the best way to move forward.
I am currently exploring using a shell to first issue a kinit command and then run the jar
I am also reading about Jaas and how this can be done in Java itself - from - https://henning.kropponline.de/2016/02/14/a-secure-hdfs-client-example/
Need inputs and any reference of available options.
My Java program that copies file is as below:
public class FileCopy implements Runnable {
#Option(names = {"-i","--input"}, required=true, description="file name to copy to hadoop")
String input;
#Option(names = {"-o","--output"}, required=true, description="hdfs directory path to be copied into")
String output;
public void run() {
Properties hadoop_properties = new Properties();
HdfsFileDeploy hdfsFileDeploy = new HdfsFileDeploy();
try {
hadoop_properties.load(FileCopy.class.getClassLoader().getResourceAsStream("hadoop.properties"));
} catch (IOException e) {
e.printStackTrace();
}
FileSystem fs = hdfsFileDeploy.configureFilesystem(hadoop_properties.getProperty("coreSitePath"),hadoop_properties.getProperty("hdfsSitePath"));
String status = hdfsFileDeploy.writeToHDFS(fs,input,output);
if (status == "SUCCESS") {
System.out.println("completed copying");
} else {
System.out.println("copying error");
}
hdfsFileDeploy.closeFileSystem(fs);
}
public static void main(String[] args) throws IOException {
CommandLine.run(new FileCopy(), args);
}
}
public class HdfsFileDeploy {
public FileSystem configureFilesystem(String coreSitePath, String hdfsSitePath) {
FileSystem fileSystem = null;
try {
Configuration conf = new Configuration();
Path hdfsCoreSitePath = new Path(coreSitePath);
Path hdfsHDFSSitePath = new Path(hdfsSitePath);
conf.addResource(hdfsCoreSitePath);
conf.addResource(hdfsHDFSSitePath);
fileSystem = FileSystem.get(conf);
System.out.println(fileSystem);
return fileSystem;
} catch (Exception ex) {
ex.printStackTrace();
return fileSystem;
}
}
public void closeFileSystem(FileSystem fileSystem) {
try {
fileSystem.close();
} catch (Exception ex) {
System.out.println("Unable to close Hadoop filesystem : " + ex);
}
}
//
public String writeToHDFS(FileSystem fileSystem, String sourcePath, String destinationPath) {
String failure = "FAILURE";
String success = "SUCCESS";
Boolean doNotDelSrc = false;
Boolean overwrite = true;
try {
Path inputPath = new Path(sourcePath);
Path outputPath = new Path(destinationPath);
if(!fileSystem.exists(outputPath)) {
System.out.println("Output path " + outputPath + " does not exist. Creating outputPath directory now..");
if (fileSystem.mkdirs(outputPath)) {
System.out.println("Output path " + outputPath + " created...");
}
}
System.out.println("about to copy from " + inputPath + " to " + outputPath);
fileSystem.copyFromLocalFile(doNotDelSrc, overwrite, inputPath, outputPath);
return success;
} catch (IOException ex) {
System.out.println("Some exception occurred while writing file to hdfs");
ex.printStackTrace();
return failure;
}
}
}
Input1: input file
Input2: target hdfs directory
Reference Input: file (say yaml) containing account, domain, keytab path.
jar should impersonate and copy the input file to target hdfs directory.
Related
I want to create a Quartz job which reads .csv files and moves them when file is processed. I tried this:
#Override
public void execute(JobExecutionContext context) {
File directoryPath = new File("C:\\csv\\nov");
// Create a new subfolder called "processed" into source directory
try {
Files.createDirectory(Path.of(directoryPath.getAbsolutePath() + "/processed"));
} catch (IOException e) {
throw new RuntimeException(e);
}
FilenameFilter textFileFilter = (dir, name) -> {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".csv")) {
return true;
} else {
return false;
}
};
// List of all the csv files
File filesList[] = directoryPath.listFiles(textFileFilter);
System.out.println("List of the text files in the specified directory:");
Optional<File> csvFile = Arrays.stream(filesList).findFirst();
File file = csvFile.get();
for(File file : filesList) {
try {
List<CsvLine> beans = new CsvToBeanBuilder(new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16))
.....
.build()
.parse();
for(CsvLine item: beans){
....... sql queries
Optional<ProcessedWords> isFound = processedWordsService.findByKeyword(item.getKeyword());
......................................
}
} catch (Exception e){
e.printStackTrace();
}
// Move here file into new subdirectory when file processing is finished
Path copied = Paths.get(file.getAbsolutePath() + "/processed");
Path originalPath = file.toPath();
try {
Files.move(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Folder processed is created when the job is started but I get exception:
2022-11-17 23:12:51.470 ERROR 16512 --- [cessor_Worker-4] org.quartz.core.JobRunShell : Job DEFAULT.keywordPostJobDetail threw an unhandled Exception:
java.lang.RuntimeException: java.nio.file.FileSystemException: C:\csv\nov\11_42_33.csv -> C:\csv\nov\processed\11_42_33.csv: The process cannot access the file because it is being used by another process
at com.wordscore.engine.processor.ImportCsvFilePostJob.execute(ImportCsvFilePostJob.java:127) ~[main/:na]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar:na]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) ~[quartz-2.3.2.jar:na]
Caused by: java.nio.file.FileSystemException: C:\csv\nov\11_42_33.csv -> C:\csv\nov\processed\11_42_33.csv: The process cannot access the file because it is being used by another process
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92) ~[na:na]
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) ~[na:na]
at java.base/sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:403) ~[na:na]
at java.base/sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:293) ~[na:na]
at java.base/java.nio.file.Files.move(Files.java:1432) ~[na:na]
at com.wordscore.engine.processor.ImportCsvFilePostJob.execute(ImportCsvFilePostJob.java:125) ~[main/:na]
... 2 common frames omitted
Do you know how I can release the file and move it into a sub directory?
EDIT: Update code with try-catch
#Override
public void execute(JobExecutionContext context) {
File directoryPath = new File("C:\\csv\\nov");
// Create a new subfolder called "processed" into source directory
try {
Path path = Path.of(directoryPath.getAbsolutePath() + "/processed");
if (!Files.exists(path) || !Files.isDirectory(path)) {
Files.createDirectory(path);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
FilenameFilter textFileFilter = (dir, name) -> {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".csv")) {
return true;
} else {
return false;
}
};
// List of all the csv files
File filesList[] = directoryPath.listFiles(textFileFilter);
System.out.println("List of the text files in the specified directory:");
Optional<File> csvFile = Arrays.stream(filesList).findFirst();
File file = csvFile.get();
for(File file : filesList) {
try {
try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){
List<CsvLine> beans = new CsvToBeanBuilder(br)
......
.build()
.parse();
for (CsvLine item : beans) {
.....
if (isFound.isPresent()) {
.........
}}
} catch (Exception e){
e.printStackTrace();
}
// Move here file into new subdirectory when file processing is finished
Path copied = Paths.get(file.getAbsolutePath() + "/processed");
Path originalPath = file.toPath();
try {
Files.move(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Quartz config:
#Configuration
public class SchedulerConfig {
private static final Logger LOG = LoggerFactory.getLogger(SchedulerConfig.class);
private ApplicationContext applicationContext;
#Autowired
public SchedulerConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public JobFactory jobFactory() {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean(Trigger simpleJobTrigger) throws IOException {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setQuartzProperties(quartzProperties());
schedulerFactory.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactory.setAutoStartup(true);
schedulerFactory.setTriggers(simpleJobTrigger);
schedulerFactory.setJobFactory(jobFactory());
return schedulerFactory;
}
#Bean
public SimpleTriggerFactoryBean simpleJobTrigger(#Qualifier("keywordPostJobDetail") JobDetail jobDetail,
#Value("${simplejob.frequency}") long frequency) {
LOG.info("simpleJobTrigger");
SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setStartDelay(1000);
factoryBean.setRepeatInterval(frequency);
factoryBean.setRepeatCount(4); // factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
return factoryBean;
}
#Bean
public JobDetailFactoryBean keywordPostJobDetail() {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(ImportCsvFilePostJob.class);
factoryBean.setDurability(true);
return factoryBean;
}
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}
Quartz config:
org.quartz.scheduler.instanceName=wordscore-processor
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
As you can see I wan to have 5 threads in order to execute 5 parallel jobs. Do you know how I can process the files without this exception?
new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)
This parts creates a resource. A resource is an object that represents an underlying heavy thing - a thing that you can have very few of. In this case, it represents an underlying OS file handle.
You must always safely close these. There are really only 2 ways to do it correctly:
Use try-with-resources
Save it to a field, and make yourself AutoClosable so the code that uses of instances of this class can use try-with-resources
try (var br = new FileReader(file, StandardCharsets.UTF_16)) {
List<CsvLine> beans = new CsvToBeanBuilder(br)
.....
.build()
.parse();
}
Is the answer.
Although I agree completely with the answer and comments of #rzwitserloot, note the following in your error stack trace:
java.nio.file.FileSystemException: C:\csv\nov\07_06_26.csv -> C:\csv\nov\07_06_26.csv\processed: The process cannot access the file because it is being used by another process
You are trying moving your file to the backup directory, but note you are doing it to the wrong path, C:\csv\nov\07_06_26.csv\processed, in the example.
Please, try the following:
#Override
public void execute(JobExecutionContext context) {
File directoryPath = new File("C:\\csv\\nov");
// Create a new subfolder called "processed" into source directory
// Hold a reference to the processed files directory path, we will
// use it later
Path processedDirectoryPath;
try {
processedDirectoryPath = Path.of(directoryPath.getAbsolutePath() + "/processed");
if (!Files.exists(processedDirectoryPath) || !Files.isDirectory(processedDirectoryPath)) {
Files.createDirectory(processedDirectoryPath);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
FilenameFilter textFileFilter = (dir, name) -> {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".csv")) {
return true;
} else {
return false;
}
};
// List of all the csv files
File filesList[] = directoryPath.listFiles(textFileFilter);
System.out.println("List of the text files in the specified directory:");
for(File file : filesList) {
try {
try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){
List<CsvLine> beans = new CsvToBeanBuilder(br)
......
.build()
.parse();
for (CsvLine item : beans) {
.....
if (isFound.isPresent()) {
.........
}}
} catch (Exception e){
e.printStackTrace();
}
// Move here file into new subdirectory when file processing is finished
// In my opinion, here is the error:
// Path copied = Paths.get(file.getAbsolutePath() + "/processed");
Path originalPath = file.toPath();
try {
// Note the use of the path we defined before
Files.move(originalPath, processedDirectoryPath.resolve(originalPath.getFileName()),
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
If you need to increase the throughput of files processed, you could try splitting them in batches, say for certain pattern in their name like a month name or a job number, for instance. The simple solution could be to use the provided JobExecutionContext of every job to include some split criteria. That criteria will be used in your FilenameFilter causing every job to process only a certain portion of the whole amount of files that need to be processed. I think the solution is preferable to any kind of locking or similar mechanism..
For example, consider the following:
#Override
public void execute(JobExecutionContext context) {
File directoryPath = new File("C:\\csv\\nov");
// Create a new subfolder called "processed" into source directory
// Hold a reference to the processed files directory path, we will
// use it later
Path processedDirectoryPath;
try {
processedDirectoryPath = Path.of(directoryPath.getAbsolutePath() + "/processed");
if (!Files.exists(processedDirectoryPath) || !Files.isDirectory(processedDirectoryPath)) {
Files.createDirectory(processedDirectoryPath);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// We obtain the file processing criteria using a job parameter
JobDataMap data = context.getJobDetail().getJobDataMap();
String filenameProcessingCriteria = data.getString("FILENAME_PROCESSING_CRITERIA");
// Use the provided criteria to restrict the files that this job
// will process
FilenameFilter textFileFilter = (dir, name) -> {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".csv") && lowercaseName.indexOf(filenameProcessingCriteria) > 0) {
return true;
} else {
return false;
}
};
// List of all the csv files
File filesList[] = directoryPath.listFiles(textFileFilter);
System.out.println("List of the text files in the specified directory:");
for(File file : filesList) {
try {
try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){
List<CsvLine> beans = new CsvToBeanBuilder(br)
......
.build()
.parse();
for (CsvLine item : beans) {
.....
if (isFound.isPresent()) {
.........
}}
} catch (Exception e){
e.printStackTrace();
}
// Move here file into new subdirectory when file processing is finished
// In my opinion, here is the error:
// Path copied = Paths.get(file.getAbsolutePath() + "/processed");
Path originalPath = file.toPath();
try {
// Note the use of the path we defined before
Files.move(originalPath, processedDirectoryPath.resolve(originalPath.getFileName()),
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
You need to pass the required parameter to your jobs:
JobDetail job1 = ...;
job1.getJobDataMap().put("FILENAME_PROCESSING_CRITERIA", "job1pattern");
An even simpler approach, based on the same idea, could be splitting the files in different folders and pass the folder name that need to be processed as a job parameter:
#Override
public void execute(JobExecutionContext context) {
// We obtain the directory path as a job parameter
JobDataMap data = context.getJobDetail().getJobDataMap();
String directoryPathName = data.getString("DIRECTORY_PATH_NAME");
File directoryPath = new File(directoryPathName);
// Create a new subfolder called "processed" into source directory
// Hold a reference to the processed files directory path, we will
// use it later
Path processedDirectoryPath;
try {
processedDirectoryPath = Path.of(directoryPath.getAbsolutePath() + "/processed");
if (!Files.exists(processedDirectoryPath) || !Files.isDirectory(processedDirectoryPath)) {
Files.createDirectory(processedDirectoryPath);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
FilenameFilter textFileFilter = (dir, name) -> {
String lowercaseName = name.toLowerCase();
if (lowercaseName.endsWith(".csv")) {
return true;
} else {
return false;
}
};
// List of all the csv files
File filesList[] = directoryPath.listFiles(textFileFilter);
System.out.println("List of the text files in the specified directory:");
for(File file : filesList) {
try {
try (var br = new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16)){
List<CsvLine> beans = new CsvToBeanBuilder(br)
......
.build()
.parse();
for (CsvLine item : beans) {
.....
if (isFound.isPresent()) {
.........
}}
} catch (Exception e){
e.printStackTrace();
}
// Move here file into new subdirectory when file processing is finished
// In my opinion, here is the error:
// Path copied = Paths.get(file.getAbsolutePath() + "/processed");
Path originalPath = file.toPath();
try {
// Note the use of the path we defined before
Files.move(originalPath, processedDirectoryPath.resolve(originalPath.getFileName()),
StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
And pass a different folder to every different job:
JobDetail job1 = ...;
job1.getJobDataMap().put("DIRECTORY_PATH_NAME", "C:\\csv\\nov");
Please, consider refactor your code and define methods for file processing, file backup, etc, it will make your code easy to understand and handle.
Assuming we have File file = new File("c:/test.txt"), and print the the following paths:
Path copied = Paths.get(file.getAbsolutePath() + "/processed");
Path originalPath = file.toPath();
We will get the result:
copied: C:\test.txt\processed
originalPath: C:\test.txt
So its incorrect. You should try to get the parent path plus the processed folder plus the file name.
Path copied = Paths.get(file.getParentFile().getAbsolutePath() + "/processed/" + file.getName());
Path originalPath = file.toPath();
The line in error message
Caused by: java.lang.RuntimeException:
java.nio.file.FileSystemException: C:\csv\nov\07_06_26.csv ->
C:\csv\nov\07_06_26.csv\processed: The process cannot access the file
because it is being used by another process
I think you want to move the file from C:\csv\nov to C:\csv\nov\processed, so
you have to change following line:
Path copied = Paths.get(file.getAbsolutePath() + "/processed");
to
Path copied = Paths.get(file.getParent() + "/processed");
because file.getAbsolutePath() returns the complete path, include the name of file.
I’m pretty sure that the file is being locked by the file reader that you create but never close in the following line:
List<CsvLine> beans = new CsvToBeanBuilder(new FileReader(file.getAbsolutePath(), StandardCharsets.UTF_16))
Refactor your code so that you have that reader in a try finally block or close it explicitly.
The unintuitive behavior you might see is that those files are released at seemingly random times. This is because when the garbage collector frees up those readers, they will then release the files. Clean them up explicitly instead.
I've been trying to read a properties file and want it to be dynamic, I'm doing this in aws-cdk.
My project layout:
Main Project
resources
config.properties
src
main/java/com/myorg
xxxstage.java
The class xxxstage.java has following code:
public class xxxstage extends Stage {
public xxxstage(final Construct scope, final String id) {
this(scope, id, null);
}
public xxxstage(final Construct scope, final String id, final StageProps props) {
super(scope, id, props);
String account = null;
InputStream inputStream = null;
try {
Properties prop = new Properties();
String propFileName = "resources/config.properties";
inputStream = this.getClass().getClassLoader().getResourceAsStream(propFileName);
System.out.println("inputStream is -> "+inputStream);
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
// get the property value and print it out
account = prop.getProperty("account.id");
System.out.println("account id -> "+account);
} catch (Exception e) {
System.out.println("Exception: " + e);
} finally {
try{
inputStream.close();
}
catch (Exception e){
System.out.println("Exception: " + e);
}
}
new xxxStack(this, "xxxStack", StackProps.builder()
.env(new Environment.Builder()
.account(account)
.region("us-east-1")
.build())
.build());
}
}
The line where I'm trying to print System.out.println("inputStream is -> "+inputStream); is showing null, and hence the FileNotFoundException.
It worth noting that this is working fine when I run it on local java-project, its however failing during build phase of the aws-codepipeline.
In the pipeline build phase I'm getting:
inputStream is -> null
Exception: java.io.FileNotFoundException: property file 'resources/config.properties' not found in the classpath
Exception: java.lang.NullPointerException
Can someone please help?
EDIT 1 - Adding environment variables:
Environment Vars
PATH=/root/.npm/_npx/230/bin:/usr/local/bin/sbt/bin:/root/.phpenv/shims:/root/.phpenv/bin:/root/.goenv/shims:/root/.goenv/bin:/go/bin:/root/.phpenv/shims:/root/.phpenv/bin:/root/.pyenv/shims:/root/.pyenv/bin:/root/.rbenv/shims:/usr/local/rbenv/bin:/usr/local/rbenv/shims:/root/.dotnet/:/root/.dotnet/tools/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/tools:/codebuild/user/bin
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/xxx-xxx-xxx
CODEBUILD_CI=true
CODEBUILD_AUTH_TOKEN=xxx-xxx-xxx
JAVA_8_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto
JDK_8_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto
CODEBUILD_BUILD_ARN=arn:aws:codebuild:us-east-1:821518525729:build/pipelinePipelinexxx-C-xxx-xxx-xxx
CODEBUILD_GOPATH=/codebuild/output/src123245
GOLANG_15_VERSION=1.15.12
CODEBUILD_BUILD_SUCCEEDING=1
GOENV_DISABLE_GOPATH=1
JRE_HOME=/usr/lib/jvm/java-11-amazon-corretto
CDK_DEFAULT_REGION=us-east-1
JAVA_11_HOME=/usr/lib/jvm/java-11-amazon-corretto
PHP_74_VERSION=7.4.13
CODEBUILD_SOURCE_VERSION=arn:aws:s3:::pipelinexxxstack-pipelinexxxartifacts-1cacuj92rramf/ServiceDeploymentPip/(user)/c1BGqPX
RUBY_BUILD_SRC_DIR=/usr/local/rbenv/plugins/ruby-build
JDK_HOME=/usr/lib/jvm/java-11-amazon-corretto
PWD=/codebuild/output/src12345/src
CODEBUILD_CONTAINER_NAME=default
PYTHON_37_VERSION=3.7.10
CODEBUILD_START_TIME=1642556874326
CDK_DEFAULT_ACCOUNT=12345
AWS_REGION=us-east-1
PYTHON_38_VERSION=3.8.10
CODEBUILD_BUILD_URL=https://us-east-1.console.aws.amazon.com/codebuild/home?region=us-east-1#/builds/pipelinePipelinexxxSynthC-ofdfmXGrWl5m:xxx-xxx-xxx/view/new
CDK_OUTDIR=cdk.out
DOTNET_31_SDK_VERSION=3.1.404
CODEBUILD_BUILD_ID=pipelinePipelinexxxSynthC-ofdfmXGrWl5m:xxx-xxx-xxx
GOPATH=/go:/codebuild/output/src12345
CODEBUILD_RESOLVED_SOURCE_VERSION=xxx-xxx-xxx
OLDPWD=/codebuild/output/src12345/src
RUBY_26_VERSION=2.6.6
AWS_STS_REGIONAL_ENDPOINTS=regional
DOTNET_ROOT=/root/.dotnet
_PROJECT_CONFIG_HASH=xxx-xxx-xxx
CODEBUILD_AGENT_ENDPOINT=http://127.0.0.1:port
LC_CTYPE=C.UTF-8
JRE_8_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto/jre
CODEBUILD_BUILD_IMAGE=aws/codebuild/standard:5.0
PYYAML_VERSION=5.4.1
FORCE_COLOR=0
CODEBUILD_BMR_URL=https://CODEBUILD_AGENT:port
JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto
CODEBUILD_SRC_DIR=/codebuild/output/src12345/src
AWS_DEFAULT_REGION=us-east-1
AWS_EXECUTION_ENV=AWS_ECS_EC2
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/xxx-xxx-xxx
ECS_CONTAINER_METADATA_URI_V4=http://169.254.170.2/v4/xxx-xxx-xxx
CODEBUILD_INITIATOR=codepipeline/ServicexxxPipeline
MAVEN_OPTS= -Dmaven.wagon.httpconnectionManager.maxPerRoute=2
CDK_CONTEXT_JSON={"#aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId":true,"#aws-cdk/core:enableStackNameDuplicates":true,"aws-cdk:enableDiffNoFail":true,"#aws-cdk/core:stackRelativeExports":true,"#aws-cdk/aws-ecr-assets:dockerIgnoreSupport":true,"#aws-cdk/aws-secretsmanager:parseOwnedSecretName":true,"#aws-cdk/aws-kms:defaultKeyPolicies":true,"#aws-cdk/aws-s3:grantWriteWithoutAcl":true,"#aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount":true,"#aws-cdk/aws-rds:lowercaseDbIdentifier":true,"#aws-cdk/aws-efs:defaultEncryptionAtRest":true,"#aws-cdk/aws-lambda:recognizeVersionProps":true,"#aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021":true,"#aws-cdk/core:newStyleStackSynthesis":true,"aws:cdk:enable-path-metadata":true,"aws:cdk:enable-asset-metadata":true,"aws:cdk:version-reporting":true,"aws:cdk:bundling-stacks":[]}
CODEBUILD_LOG_PATH=xxx-xxx-xxx
CODEBUILD_EXECUTION_ROLE_BUILD=
CODEBUILD_BUILD_NUMBER=31
GOLANG_16_VERSION=1.16.4
PHP_73_VERSION=7.3.25
CODEBUILD_FE_REPORT_ENDPOINT=https://codebuild.us-east-1.amazonaws.com/
CODEBUILD_LAST_EXIT=0
AWS_NODEJS_CONNECTION_REUSE_ENABLED=1
MAVEN_CMD_LINE_ARGS= -e -q compile exec:java
NUGET_XMLDOC_MODE=skip
DOTNET_5_SDK_VERSION=5.0.202
NODE_12_VERSION=12.22.2
PYTHON_39_VERSION=3.9.5
CDK_CLI_VERSION=2.8.0
NODE_14_VERSION=14.17.2
MAVEN_PROJECTBASEDIR=/codebuild/output/src12345/src
CDK_CLI_ASM_VERSION=16.0.0
JRE_11_HOME=/usr/lib/jvm/java-11-amazon-corretto
RUBY_27_VERSION=2.7.2
HOSTNAME=12345
JDK_11_HOME=/usr/lib/jvm/java-11-amazon-corretto
CODEBUILD_PROJECT_UUID=xxx-xxx-xxx
PHP_80_VERSION=8.0.0
CODEBUILD_KMS_KEY_ID=arn:aws:kms:us-east-1:(account-num):alias/aws/s3
HOME=/root
I found an answer here and it worked for me. The location of properties file matters.
As I am very new to Apache-Camel, I stuck with a use case.
I want to achieve moving of all files to a specific directory without sub-directories in target using camel route,
for example-
SourceDirectory/file1.xml
SourceDirectory/subDir1/file2.xml
SourceDirectory/subDir2/file3.xml
SourceDirectory/subDir3/subDir4/file4.xml
should be moved to a destination Directory
destDir/file1.xml
destDir/file2.xml
destDir/file3.xml
destDir/file4.xml
The code below copies file including all sub-directories to destination
String src="ftp://username:password#host/srcDir/";
String destDir="ftp://username:password#host/destDir/";
fromUri = src+"?recursive=true&delete=true";
from(fromUri)
.to(destDir);
To achieve this currently I am using ftp client
private void moveOverFTP(String from, String to) {
FTPClient ftpClient = new FTPClient();
try {
URL url = new URL(from);
String[] info = url.getUserInfo().split(":");
ftpClient.connect(url.getHost());
ftpClient.login(info[0], info[1]);
String srcFolderPath = url.getPath();
String targetFolder = new URL(to).getPath();
move(srcFolderPath, targetFolder, ftpClient);
ftpClient.logout();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
private void move(String srcFolderPath, String targetFolder, FTPClient ftpClient) throws IOException {
FTPFile[] files = ftpClient.listFiles(srcFolderPath);
for (FTPFile file : files) {
String fileName = file.getName();
if (file.isDirectory()) {
String tempSrcPath = srcFolderPath + fileName + "/";
move(tempSrcPath, targetFolder, ftpClient);
// delete empty directory
ftpClient.removeDirectory(tempSrcPath);
} else {
System.out.println("Moving "+srcFolderPath + fileName +" to = "+ targetFolder);
ftpClient.rename(srcFolderPath + fileName, targetFolder + fileName);
}
}
}
Any help to achieve this in route itself would be appreciated!
Thank you in advance!
Sounds like what you are looking for is the flatten option, ie.:
from(fromUri)
.to(destDir + "?flatten=true");
I am using a Windows machine and Java. I'm just trying to backup a file, but I ran into an issue with an illegal character in the path ("#"). I really tried and I'm stuck. I rewrote it trying all the variations I could find or think of. Any help would be greatly appreciated.
public class SyncActionMachine {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, URISyntaxException {
String MSI_one, MSI_two, dropBox;
GetDate getDate = new GetDate();
MSI_one = "C:\\Users\\Brian\\AppData\\Roaming\\Macromedia\\Flash Player\\#SharedObjects\\Q2965ZS7\\localhost\\ActionMachine.sol";
MSI_two = "C:\\Users\\Brian\\Desktop\\test.txt";
dropBox = "C:\\Users\\Brian\\Dropbox\\Action Machine History\\ActionMachine.sol";
File source = new File(MSI_one);
File destination = new File(dropBox);
// Attempt #1 using string with special characters
try {
Files.copy(source.toPath(), destination.toPath());
} catch (IOException iOException) {
System.out.println("Didn't work: " + iOException);
}
// Attempt #2 using URI - not really sure how to use it.
URI uri;
uri = new URI("file:///C:/Users/Brian/AppDate/Roaming/Macromedia/Flash%20Player/%23SharedObjects/Q2965ZS7/localhost/ActionMachine.sol");
Path uriSelfMadePath = Paths.get(uri);
try {
Files.copy(uriSelfMadePath, destination.toPath());
} catch (IOException iOException) {
System.out.println("Didn't work: " + iOException);
}
// Attempt #3 Suggestion from Aurasphere. Thanks again for quick response.
// Not sure what I'm suppose to do with the URL
String thePath = MSI_one;
thePath = URLEncoder.encode(thePath, "UTF-8");
Path aurasphereThePath = Paths.get(thePath);
try {
Files.copy(aurasphereThePath, destination.toPath());
} catch (IOException iOException) {
System.out.println("Didn't work: " + iOException);
}
// Attempt #4 build path using Patha and passing in augruments separately
Path pathOneByOne = Paths.get("C:", "Users", "Brian", "AppDate", "Roaming", "Macromedia", "Flash Player",
"#SharedObjects", "Q2965ZS7", "localhost", "ActionMachine.sol");
try {
Files.copy(pathOneByOne, destination.toPath());
} catch (IOException iOException) {
System.out.println("Didn't work: " + iOException);
}
// Seeing what all these path's look like
URL fileUrl = source.toURI().toURL();
URI fileUri = source.toURI();
System.out.println("------------Path Print out------------------");
System.out.println("URLEncoder : " + thePath);
Path from = Paths.get(fileUri);
System.out.println("URL : " + fileUrl);
System.out.println("URI : " + fileUri);
System.out.println("source: " + source);
}
}
Thanks for any advice.
Just use URLEncode:
String thePath = "your_path";
thePath = URLEncoder.encode(thePath, "UTF-8");
Thank you everyone that looked and commented. Must have been some sleep derived moment. Anyway here is the source, it worked fine. Turned out # was a big deal, I'm not even sure what my hang up was.
public static void main(String[] args) throws IOException, URISyntaxException {
String MSI_one, MSI_two, dropBox;
GetDate getDate = new GetDate();
MSI_one = "C:\\Users\\Brian\\AppData\\Roaming\\Macromedia\\Flash Player\\#SharedObjects\\Q2965ZS7\\localhost\\ActionMachine.sol";
MSI_two = "C:\\Users\\brian\\AppData\\Roaming\\Macromedia\\Flash Player\\#SharedObjects\\HSTARDTM\\localhost\\ActionMachine.sol";
dropBox = "C:\\Users\\brian\\Dropbox\\Action Machine History\\";
// Create new file name for backup file
dropBox = dropBox + "ActionMachine-" + getDate.today() + ".sol";
File source = new File(MSI_two);
File destination = new File(dropBox);
copyNewFile cf = new copyNewFile(source, destination);
}
public class copyNewFile {
public copyNewFile(File source, File dest) throws IOException {
CopyOption[] options = new CopyOption[]{
StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES
};
Files.copy(source.toPath(), dest.toPath(), options);
System.out.println("File sucessfully copied.");
}
}
My programm shall communicate via RS232, therefore i use a .jar and two .dll's from RXTX. At the end I want to run it from a single .jar file.
To solve this problem i used this tutorial. But if I run the program from Eclipse (or after exporting from console) I get this exception:
java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown while loading gnu.io.RXTXCommDriver
Exception in thread "main" java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path
Here is an minimal example of my code
private static final String LIB = "lib/";
private final static String RXTXPARALLEL = "rxtxParallel";
private final static String RXTXSERIAL = "rxtxSerial";
static {
try {
System.loadLibrary(RXTXSERIAL);
System.loadLibrary(RXTXPARALLEL);
} catch (UnsatisfiedLinkError e) {
loadFromJar();
}
}
public static void main(String[] args) {
//RS232 is this class
RS232 main = new RS232();
main.connect("COM15");
}
private static void loadFromJar() {
String path = "AC_" + new Date().getTime();
loadLib(path, RXTXPARALLEL);
loadLib(path, RXTXSERIAL);
}
private static void loadLib(String path, String name) {
name = name + ".dll";
try {
InputStream in = ResourceLoader.load(LIB + name);
File fileOut = new File(System.getProperty("java.io.tmpdir") + "/"
+ path + LIB + name);
OutputStream out = FileUtils.openOutputStream(fileOut);
IOUtils.copy(in, out);
in.close();
out.close();
System.load(fileOut.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
private void connect(String portName) {
CommPortIdentifier portIdentifier;
try {
//Here the exception is thrown
portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
} catch (NoSuchPortException exc) {
exc.printStackTrace();
return;
}
//... some other code
}
Is there a way to get an executable .jar file?
You have a few options. Try to copy the .dll files in the runtime folder and override the files at each start of your program. A second option is to copy the files in a fix folder and add the path of the folder to the environment variables in MS Windows. You can also override the files at each start.
Another possibility is to add the temporary folder to the MS Windows environment variables at runntime. But be careful with this solution, for more information read this post.
static {
try {
System.loadLibrary(RXTXSERIAL);
System.loadLibrary(RXTXPARALLEL);
} catch (UnsatisfiedLinkError exc) {
initLibStructure();
}
}
private static void initLibStructure() {
try {
//runntime Path
String runPath = new File(".").getCanonicalPath();
//create folder
File dir = new File(runPath + "/" + LIB);
dir.mkdir();
//get environment variables and add the path of the 'lib' folder
String currentLibPath = System.getProperty("java.library.path");
System.setProperty("java.library.path",
currentLibPath + ";" + dir.getAbsolutePath());
Field fieldSysPath = ClassLoader.class
.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
loadLib(runPath, RXTXPARALLEL);
loadLib(runPath, RXTXSERIAL);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void loadLib(String path, String name) {
name = name + ".dll";
try {
InputStream in = ResourceLoader.load(LIB + name);
File fileOut = new File(path + "/" + LIB + name);
OutputStream out = FileUtils.openOutputStream(fileOut);
IOUtils.copy(in, out);
in.close();
out.close();
System.load(fileOut.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}