dataanon / dataanon-kotlin-sample

Kotlin Sample Project for Data Anonymization Tool
0 stars 0 forks source link

Resource not found by dependency jar #2

Open zluiten opened 6 years ago

zluiten commented 6 years ago

I've modified this sample project quite a bit. I added a new RandomFullName strategy that actually uses seperate resource files for male and female first names. It basically is a modified version of the com.github.dataanon.strategy.name.RandomFullName class.

package com.netiul.db.anonymizer.strategy

import com.github.dataanon.model.Field
import com.github.dataanon.model.Record
import com.github.dataanon.strategy.AnonymizationStrategy
import com.github.dataanon.strategy.list.PickFromFile
import java.util.*

class RandomFullName(femaleFirstNameSourceFilePath: String = RandomFullName::class.java.getResource("/data/female_first_names.dat").path,
                     maleFirstNameSourceFilePath:  String = RandomFullName::class.java.getResource("/data/male_first_names.dat").path,
                     lastNameSourceFilePath:  String = RandomFullName::class.java.getResource("/data/last_names.dat").path) : AnonymizationStrategy<String> {

    init {
        require(femaleFirstNameSourceFilePath.isNotBlank(), {"femaleFirstNameSourceFilePath can not be empty while using RandomFullName"})
        require(maleFirstNameSourceFilePath.isNotBlank(), {"maleFirstNameSourceFilePath can not be empty while using RandomFullName"})
        require(lastNameSourceFilePath.isNotBlank(),  {"lastNameSourceFilePath can not be empty while using RandomFullName"})
    }

    private val femalePickFirstNames = PickFromFile<String>(filePath = femaleFirstNameSourceFilePath)
    private val malePickFirstNames = PickFromFile<String>(filePath = maleFirstNameSourceFilePath)
    private val pickLastNames  = PickFromFile<String>(filePath = lastNameSourceFilePath)

    override fun anonymize(field: Field<String>, record: Record): String = when (Random().nextBoolean()) {
        true    -> "${femalePickFirstNames.anonymize(field, record)} ${pickLastNames.anonymize(field, record)}"
        else    -> "${malePickFirstNames.anonymize(field, record)} ${pickLastNames.anonymize(field, record)}"
    }
}

I build the executable jar file with mvn package, but when running the jar file it gives me the following error about the resource not being found, although its in the jar file.

Exception in thread "main" java.io.FileNotFoundException: file:/Users/netiul/Repositories/netiul-db-anonymizer/target/netiul-db-anonymizer.jar!/data/female_first_names.dat (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at kotlin.io.FilesKtFileReadWriteKt.forEachLine(FileReadWrite.kt:156) at kotlin.io.FilesKtFileReadWriteKt.readLines(FileReadWrite.kt:185) at kotlin.io.FilesKt__FileReadWriteKt.readLines$default(FileReadWrite.kt:183) at com.github.dataanon.utils.FlatFileContentStore.getFileContentPostRead(FlatFileContentStore.kt:16) at com.github.dataanon.utils.FlatFileContentStore.getFileContentByPath(FlatFileContentStore.kt:12) at com.github.dataanon.strategy.list.PickFromFile.(PickFromFile.kt:16) at com.netiul.db.anonymizer.strategy.RandomFullName.(RandomFullname.kt:20) at com.netiul.db.anonymizer.strategy.RandomFullName.(RandomFullname.kt:12) at com.netiul.db.anonymizer.AnonymizerKt$main$58.invoke(Anonymizer.kt:227) at com.netiul.db.anonymizer.AnonymizerKt$main$58.invoke(Anonymizer.kt) at com.github.dataanon.dsl.Whitelist.table(Whitelist.kt:12) at com.netiul.db.anonymizer.AnonymizerKt.main(Anonymizer.kt:224)

I'm not very experienced with java/kotlin, but if I understand this correctly: the resource inside the generated jar-file must be accessible from the dependency-jar (data-anon-0.9.4.jar), but somehow does not have access.

The pom.xml is pretty much unchanged from this sample project (except for a few extra dependencies).

I've put quite some time now in this issue and it's driving me crazy 😏 . Any idea how this can solved? Thanks a lot!!

SarthakMakhija commented 6 years ago

Hello,

I am assuming that you creating RandomFullName in this sample project.

RandomFullName is a strategy which relies on PickFromFile which internally uses FlatFileContentStore to load the .dat file.

FlatFileContentStore uses File(this::class.java.getResource("/data/").path) to load all the resources present under /data/ directory.

Since, FlatFileContentStore uses File(..) it probably is not able to access resources outside JAR. But, will check and come back to you.

zluiten commented 6 years ago

I am assuming that you creating RandomFullName in this sample project.

RandomFullName is a strategy which relies on PickFromFile which internally uses FlatFileContentStore to load the .dat file.

That's correct. I copied (and modified the RandomFullName to the sample project) which indeed uses the class FlatFileContentStore from data-anon.jar file.

Since, FlatFileContentStore uses File(..) it probably is not able to access resources outside JAR. But, will check and come back to you.

That clarifies a bit. I assumed that as long as the resources are in the class path it should be able to find the file, but that might not be the case then.

Thanks for looking into this! I said it before, nice project this is!

SarthakMakhija commented 6 years ago

Thanks for the feedback .. we will get back to you shortly