I know that we can access private constructor via reflection as #Sanjay T. Sharma mentioned in his answer of my question: Does “instanceof Void” always return false?
However, #duffymo said:
you can access private everything with reflection - methods, constructors, data members, everything.
How can I access the private methods and the private data members?
Is it possible to access local variable via reflection?
Is there a way to prevent anyone from accessing private constructors, methods, and data members?
1) How can I access the private methods and the private data members?
You can do it with a little help of the setAccessible(true) method:
class Dummy{
private void foo(){
System.out.println("hello foo()");
}
private int i = 10;
}
class Test{
public static void main(String[] args) throws Exception {
Dummy d = new Dummy();
/*--- [INVOKING PRIVATE METHOD] ---*/
Method m = Dummy.class.getDeclaredMethod("foo");
//m.invoke(d); // Exception java.lang.IllegalAccessException
m.setAccessible(true);//Abracadabra
m.invoke(d); // Now it's OK
/*--- [GETING VALUE FROM PRIVATE FIELD] ---*/
Field f = Dummy.class.getDeclaredField("i");
//System.out.println(f.get(d)); // Not accessible now
f.setAccessible(true); // Abracadabra
System.out.println(f.get(d)); // Now it's OK
/*--- [SETTING VALUE OF PRIVATE FIELD] ---*/
Field f2 = Dummy.class.getDeclaredField("i");
//f2.set(d,20); // Not accessible now
f2.setAccessible(true); // Abracadabra
f2.set(d, 20); // Now it's OK
System.out.println(f2.get(d));
}
}
2) Is it possible to access a local variable via reflection?
No. Local variables cannot be accessed outside of a block in which they were created (someone could say that you can assign such a variable to a field like field = localVariable; and later access such a field via reflection, but this way we will be accessing the value, not the variable).
3) Is there any way to prevent anyone from accessing private constructors, methods, and data members?
I think for constructors or methods you could use stacktrace to check if it was invoked by Reflection.
For fields I can't find a solution to prevent accessing them via reflection.
[WARNING: This is not approved by anyone. I just wrote it inspired by your question.]
class Dummy {
private void safeMethod() {
StackTraceElement[] st = new Exception().getStackTrace();
// If a method was invoked by reflection, the stack trace would be similar
// to something like this:
/*
java.lang.Exception
at package1.b.Dummy.safeMethod(SomeClass.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-> at java.lang.reflect.Method.invoke(Method.java:601)
at package1.b.Test.main(SomeClass.java:65)
*/
//5th line marked by "->" is interesting one so I will try to use that info
if (st.length > 5 &&
st[4].getClassName().equals("java.lang.reflect.Method"))
throw new RuntimeException("safeMethod() is accessible only by Dummy object");
// Now normal code of method
System.out.println("code of safe method");
}
// I will check if it is possible to normally use that method inside this class
public void trySafeMethod(){
safeMethod();
}
Dummy() {
safeMethod();
}
}
class Dummy1 extends Dummy {}
class Test {
public static void main(String[] args) throws Exception {
Dummy1 d1 = new Dummy1(); // safeMethod can be invoked inside a superclass constructor
d1.trySafeMethod(); // safeMethod can be invoked inside other Dummy class methods
System.out.println("-------------------");
// Let's check if it is possible to invoke it via reflection
Method m2 = Dummy.class.getDeclaredMethod("safeMethod");
// m.invoke(d);//exception java.lang.IllegalAccessException
m2.setAccessible(true);
m2.invoke(d1);
}
}
Output from Test main method:
code of safe method
code of safe method
-------------------
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at package1.b.Test.main(MyClass2.java:87)
Caused by: java.lang.RuntimeException: method safeMethod() is accessible only by Dummy object
at package1.b.Dummy.safeMethod(MyClass2.java:54)
... 5 more
Using the method shown in the answer you linked to: setAccessible(true), which is a method of the superclass of Field, Constructor and Method.
No.
No, unless the code runs in a JVM you control, where you install a security manager. But if you give someone a jar file, and he uses the classes from this jar file, he'll be able to access everything.
To access a private field you will need to call the
Class.getDeclaredField(String name) or enter code here method.
Check this simple code:
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue
To access a private method you will need to call the Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods() method.
Check this simple code:
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
private String getPrivateString(){
return this.privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);
String returnValue = (String)
privateStringMethod.invoke(privateObject, null);
System.out.println("returnValue = " + returnValue);
Read detail at
http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html
Area s=(Area)c.newInstance();
s.setRadius(10);
System.out.println("Area: "+s.calculateArea(4));
Method m[]=c.getDeclaredMethods();
Constructor c1[]=c.getConstructors();
for(int i=0;i<m.length;i++)
System.out.println(""+m[i]);
for(int i=0;i<c1.length;i++)
System.out.println(""+c1[i]);
Example as below:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Test
{
private int a = 5; // Private data member
private void call(int n) // Private method
{
System.out.println("in call() n: " + n);
}
}
public class Sample
{
public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException
{
Class c = Class.forName("Test");
Object obj = c.newInstance();
//---- Accessing a private method
Method m=c.getDeclaredMethod("call",new Class[]{int.class});
m.setAccessible(true);
m.invoke(obj,7);
//---- Accessing a private data member
Field d = c.getDeclaredField("a");
d.setAccessible(true);
System.out.println(d.getInt(obj));
}
}
To answer your third question:
Is there a way to prevent anyone from accessing private constructors, methods, and data members?
Answer:
Yes, you can restrict the access (you can throw an exception when someone tries to access your private constructor/method/data)
Refer to the below example:
******JavaSingleton Class******
package server;
public class JavaSingleton {
private static final JavaSingleton INSTANCE = new JavaSingleton();
private JavaSingleton() {
if (INSTANCE != null) {
throw new IllegalStateException("Inside JavaSingleton(): JavaSingleton " +
"instance already created.");
}
System.out.println("Inside JavaSingleton(): Singleton instance is being created.");
}
public static final JavaSingleton getInstance() {
return INSTANCE;
}
}
***Listing 2: JavaSingleton client***
import server.JavaSingleton;
import java.lang.reflect.*;
public class TestSingleton {
public static void main(String[] args) throws ReflectiveOperationException {
System.out.println("Inside main(): Getting the singleton instance using getInstance()...");
JavaSingleton s = JavaSingleton.getInstance();
System.out.println("Inside main(): Trying to use reflection to get another instance...");
Class<JavaSingleton> clazz = JavaSingleton.class;
Constructor<JavaSingleton> cons = clazz.getDeclaredConstructor();
cons.setAccessible(true);
JavaSingleton s2 = cons.newInstance();
}
}
Output:
C:\singleton>java TestSingleton
Inside main(): Getting the singleton instance using getInstance()...
Inside JavaSingleton(): Singleton instance is being created.
Inside main(): Trying to use reflection to get another instance...
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at TestSingleton.main(TestSingleton.java:13)
Caused by: java.lang.IllegalStateException: Inside JavaSingleton(): JavaSingleton instance already created.
at server.JavaSingleton.<init>(JavaSingleton.java:7)
... 5 more
This example was for a singleton class (checking in the constructor), but you can still implement this logic for the private methods that you want to prevent access from other classes.
In this case you will also declare a static instance and check the value of it in the private method and throw an error in case of any unwanted value.
Related
I want to access one or many classes from an entry point(main) without importing package. For example:
package com.ank.dynamicJarFileCreation;
public class revDemo {
public static int reverseNumber(int n)
{
int rem,rev=0;
while(n>0)
{
rem=n%10;
rev=rev*10 + rem;
n=n/10;
}
return rev;
}
}
above one is revDemo class and I want to access above reverseNumber(int n) method from an entry point below. For example:
public class revCall {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
int n=485154;
System.out.println(revDemo.reverseNumber(n));
Or by this way.
Class cls = Class.forName("reverseDemo");
Object obj = cls.newInstance();
System.out.print("Class Name"+cls.getName());
Object obj = null; //It is a object of -> com.ank.dynamicJarFileCreationo
System.out.println(((com.ank.dynamicJarFileCreation)obj).reverseNumber(n));
}
}
You are very near to your own solution. Actually you created the instance of your required class dynamically using Class.forName() and newInstance() functions.
Next step is to get the Function from the Class by the name of method, say reverseNumber and execute the same using created instance of revDemo .
Class revDemoClazz = Class.forName("com.ank.dynamicJarFileCreation.revDemo");
Object revDemoObj = revDemoClazz.newInstance();
Method reverseNumberMethod = revDemoClazz.getMethod("reverseNumber", Integer.class);
reverseNumberMethod.invoke(revDemoObj, 12345);
Error:
...
Caused by: java.lang.ExceptionInInitializerError
...
Caused by: java.lang.ClassCastException:
class com.evopulse.ds2150.TechTrees$BuildingTechTree
not an enum
at java.util.EnumSet.noneOf(Unknown Source)
at java.util.EnumSet.of(Unknown Source)
at com.evopulse.ds2150.TechTrees$BuildingTechTree.<clinit>(TechTrees.java:38)
Here is a snippet of my enumeration
public enum BuildingTechTree {
//Name SoftName Requirements
NONE ("NULL", null),
--> This next line is where it crashes
BARRACKS ("Barracks", EnumSet.of(NONE),
WALLS_SANDBAGS ("Sandbag wall", EnumSet.of(NONE),
POWERPLANT ("Power plant", EnumSet.of(BARRACKS)),
GUARDTOWER ("Guard Tower", EnumSet.of(BARRACKS));
Replacing EnumSet.of(NONE) and EnumSet.of(BARRACKS) with null, lets initialization work, but breaks my code, due to missing data structure... obviously, but I did it to test the rest of my code wasn't somehow the cause.
Removing EnumSet.of(NONE) and replacing with just NONE, and the same for BARRACKS, and changing all related variables, constructor, and methods, that didn't work either... (and even couldn't use the contains.all, since is wasn't "applicable to my changed variable"... )
I extended this example, using the second implementation:
https://gamedev.stackexchange.com/a/25652/48573
I also tried retracing my steps by copying the example verbatim. added
private static Set<BuildingTechTree> techsKnown;
techsKnown = (BuildingTechTree.BIODOME);
test = TechTrees.researchTech(techsKnown);
to another class to be called from for testing initialization. and had to change
public boolean researchTech(BuildingTechTree tech) {
to static
This resulted in the same "in not an enum" error. I don't have any rep, to comment on his answer to point out the initialization error...
Added info for both current answers, as both solutions cause the same new error:
public class TechTrees {
private static Set<BuildingTechTree> techsKnown;
public TechTrees() {
techsKnown = EnumSet.of(BuildingTechTree.NONE); //Using this
techsKnown = EnumSet.noneOf(BuildingTechTree.class); //Or this
}
public static boolean researchTech(BuildingTechTree tech) {
if (techsKnown.containsAll(tech.requirements)) { //Causes null pointer
return true; //exception # techsKnown
}
return false;
}
Your declaration structure is so clever it's a shame it doesn't work. But EnumSet apparently needs the enum to be fully initialized first. It tries to fetch the array of constants from the enum so that, among other things, it knows how much space is needed for its internal bitset.
Here's one workaround. It uses a helper method that creates an ordinary set (HashSet) first, and then, in a static initialization block, it iterates the enum constants and replaces all the sets with EnumSets.
public enum BuildingTechTree {
// Named constants
//Name SoftName Requirements
NONE ("NULL", null),
BARRACKS ("Barracks", setOf(NONE)),
WALLS_SANDBAGS ("Sandbag wall", setOf(NONE)),
POWERPLANT ("Power plant", setOf(BARRACKS)),
GUARDTOWER ("Guard Tower", setOf(BARRACKS));
private final String softName;
private Set<BuildingTechTree> requirements;
private BuildingTechTree(String softName, Set<BuildingTechTree> requirements) {
this.softName = softName;
this.requirements = requirements;
}
private static Set<BuildingTechTree> setOf(BuildingTechTree... values) {
return new HashSet<>(Arrays.asList(values));
}
static {
for (BuildingTechTree v : values()) {
if (v.requirements == null) {
v.requirements = EnumSet.noneOf(BuildingTechTree.class);
} else {
v.requirements = EnumSet.copyOf(v.requirements);
}
}
}
}
You have a chicken and egg problem. You could refactor your enum to something like this:
public enum BuildingTechTree {
NONE("NULL"),
BARRACKS("Barracks"),
WALLS_SANDBAGS("Sandbag wall"),
POWERPLANT("Power plant"),
GUARDTOWER("Guard Tower");
static {
NONE.trees = EnumSet.noneOf(BuildingTechTree.class);
BARRACKS.trees = EnumSet.of(NONE);
WALLS_SANDBAGS.trees = EnumSet.of(NONE);
POWERPLANT.trees = EnumSet.of(BARRACKS);
GUARDTOWER.trees = EnumSet.of(BARRACKS);
}
private String name;
private Set<BuildingTechTree> trees;
private BuildingTechTree(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Set<BuildingTechTree> getTrees() {
return Collections.unmodifiableSet(trees);
}
}
EDIT:
regarding your second problem: you're accessing a static variable, from a static method. But this variable is initialized when the constructor of the class has been called (which is a huge design problem). Don't use non-final static fields. And don't initialize static fields from instance methods or constructors. That doesn't make sense. You don't set the color that all cars should have when constructing a car. Initialize your static fields statically:
public class TechTrees {
private static final Set<BuildingTechTree> TECHS_KNOWN =
EnumSet.of(BuildingTechTree.NONE);
public static boolean researchTech(BuildingTechTree tech) {
return TECHS_KNOWN.containsAll(tech.requirements));
}
}
I have already done research on this question, and also tried to figure it out by myself but no luck. So I decided to ask it.
Basic info:
There are two classes. FBClient, and State. In FBClient, I have a static variable of it's type, fbc, a StateManager instance, which just has some methods to work with State stuff, some constants and two getters. In State, I am trying to initialize a BufferedImage.
public class FBClient
{
//Static
public static FBClient fbc;
//In init method
private StateManager stateManager;
//Constants
private final int INIT_FRAME_WIDTH = 320, INIT_FRAME_HEIGHT = (INIT_FRAME_WIDTH / 4) * 3, SCALE = 3, FRAME_WIDTH = INIT_FRAME_WIDTH * SCALE, FRAME_HEIGHT = INIT_FRAME_HEIGHT * SCALE;
public static void main(String[] args)
{
try
{
//First call in exception chain:
fbc = new FBClient();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
private FBClient()
throws IOException
{
//Second call in exception chain:
init();
}
private void init()
throws IOException
{
stateManager = new StateManager();
//Third call in exception chain:
stateManager.addState(new MainMenu((byte) 0, "Main Menu")); //MainMenu is the subclass of State, and the constructor just calls "super(0, "Main Menu")"
}
public int getFRAME_HEIGHT()
{
return FRAME_HEIGHT;
}
public int getFRAME_WIDTH()
{
return FRAME_WIDTH;
}
}
public abstract class State
{
protected final byte ID;
protected final String NAME;
protected final BufferedImage SCREEN;
protected final Graphics2D GRAPHICS;
public State(byte id, String name)
{
this.ID = id;
this.NAME = name;
//Exception cause:
this.SCREEN = new BufferedImage(FBClient.fbc.getFRAME_WIDTH(), FBClient.fbc.getFRAME_HEIGHT(), BufferedImage.TYPE_INT_RGB);
this.GRAPHICS = SCREEN.createGraphics();
}
}
More info:
If I put literals in BufferedImage initialization it works.
If I initialize two variables in the State class, assigning them literals and putting those variables in initialization, it works.
If instead of assigning literals to those variables I assign them FBClient.fbc.getFRAME_WIDTH() and FBClient.fbc.getFRAME_HEIGHT(), it throws a NullPointerException.
If I make a System.out.println(getFRAME_WIDTH + " : " + getFRAME_HEIGHT) in FBClient class, it prints out properly, but if I do it in State class (and off course adding FBClient.fbc. before it), it throws a NullPointerException.
If I make FRAME_WIDTH and FRAME_HEIGHT constants public, and I try to access them from State
class by doing FBClient.fbc.FRAME_WIDTH and FRAME_HEIGHT, it throws a NullPointerException.
If I try to access the constants from FBClient class directly, instead of getters, it still prints out properly.
Finally
Thank you for taking your time, and if you need more information to work with, ask me in the comments and I'll provide it. Also, I apologise if the question is not constructed well/not explained well. If that's the case, tell me how can I improve it. And also, I apologise if this question was asked and answered once already, I may have missed it, but as I said, I did my research.
Edit #1
A comment suggested I print out a fbc value, to see if it's null.
So I added this line of code to the State constructor:
if(FBClient.fbc != null) System.out.println("Not null"); else System.out.println("Null");
And, as suspected, it printed out null. Why is that? I clearly initialized the variable in the main method...
You are referring to FBClient.fbc before it is assigned (actually in the constructor since fbc get assigned after the constructor finished working). To fix it add static to the final values, make the getter static and acess it with FBClient.getFRAME_HEIGHT(). You don't need non-static final variables.
The reason you are having a problem is because you are trying to reference FBClient.fbc within its constructor call and the object hasn't finished its own construction. It's not immediately obvious you're doing this but if you follow the code within the constructor you are calling init() which ultimately calls to a State constructor, which in turn tries to use FBClient.fbc.getFRAME_WIDTH().
I suggest you don't call init() within the FBClient constructor and change your main method code to:
public static void main(String[] args)
{
try
{
//First call in exception chain:
fbc = new FBClient();
fbc.init();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
Hope this helps.
I think your FBClient.fbc is null.
I've defined the following enum in Groovy, though for the purpose of this question it could be Java code:
enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static Set<String> allSearchTokens = new HashSet<String>();
FestivalType() {
String searchToken = this.name().tokenize('_').first().toLowerCase();
if (searchToken in allSearchTokens) {
throw new RuntimeException("Duplicate search token");
} else {
this.searchToken = searchToken;
allSearchTokens.add(searchToken);
}
}
final String searchToken;
}
What I'm trying to do in the constructor is establish whether the first token in the name of each enum constant is unique, where _ is used as the token separator.
However, this code doesn't work because allSearchTokens is not initialized until after all the constants are instantiated, so I get a NullPointerException here
allSearchTokens.add(searchToken)
You can work around this as follows:
public enum FestivalType {
BIG_MUSIC,
SMALL_MUSIC,
FILM,
FOOD_AND_DRINK;
private static class SetHolder {
static Set<String> allSearchTokens = new HashSet<String>();
}
final String searchToken;
FestivalType() {
String searchToken = name().split("_")[0].toLowerCase();
if (SetHolder.allSearchTokens.contains(searchToken))
throw new RuntimeException("Duplicate search token");
this.searchToken = searchToken;
SetHolder.allSearchTokens.add(searchToken);
}
}
This compiles because of the java specification that all static initializers must be completed before the class is used. By making the Set a static field of a sttic inner class, you guarantee that it will be initialized before the first enum is constructed.
Also, I took the liberty of changing/fixing a few things in your code:
Use a Set rather than a List: Values are unique
Use split(): There is not such method tokenize() for String in java
Remove else: After a return or throws, else is always redundant because execution of the block is halted by these keywords (there is no "else" to handle)
As an aside, this technique is also great for lazy initialization of singletons:
public class MyLazySingleton() {
private static class InstanceHolder {
static MyLazySingleton INSTANCE = new MyLazySingleton();
}
public static MyLazySingleton getInstance() {
return InstanceHolder.INSTANCE;
}
}
The INSTANCE field is only constructed when the getInstance() method is first called!
Look mom! Lazy initialization without locks, without null checks, without synchronization of any kind and 100% bulletproof! (Object deserialization hacks notwithstanding)
It's magic :)
I have done something similar and the following has worked for me:
enum MyEnum{
Enum1, Enum2;
private static List<String> myList;
private static void addToList(MyEnum enum){
if(myList == null){
myList = new ArrayList<String>();
}
myList.add(enum.name());
}
private MyEnum(){
addToList(this);
}
}
Parent class(*ch.qos.logback.core.FileAppender*):
...
protected String fileName = null;
public FileAppender() {
}
public void setFile(String file) {
if (file == null) {
fileName = file;
} else {
// Trim spaces from both ends. The users probably does not want
// trailing spaces in file names.
String val = file.trim();
fileName = val;
}
}
...
Child class:
...
public class FileAppender<E> extends ch.qos.logback.core.FileAppender<E> {
private FileResourceManager frm = new FileResourceManager(fileName, tempDir, false, loggerFacade);
public void writeOut(E event) throws IOException {
Object txId = null;
try {
frm.start();
txId = frm.generatedUniqueTxId();
frm.startTransaction(txId);
outputStream = frm.writeResource(txId, fileName, true);
outputStream.write(event.toString().getBytes());
frm.commitTransaction(txId);
}
catch (Exception e) {
...
}
}
The problem is that fileName is passed as null to frm in this line:
private FileResourceManager frm = new FileResourceManager(fileName, tempDir, false, loggerFacade);
How can i create frm instance,with not-null fileName,e.g. already initialized in parent?
If I understand your question correctly, you can do one of the following:
call setFile(file) in constructor of child class
implement logics placed in setFile() method in child's constructor (BTW, that'll be code duplication)
if parent class provides constructor, which accepts file parameter, call parent's constructor with super(file) in constructor of child class
UPDATE
AFAIU, the problem is in fields initialization order. The moving "frm" field initialization into child class constructor should solve the problem:
public FileAppender(String fileName) {
setFile(fileName);
frm = new FileResourceManager(fileName, tempDir, false, loggerFacade);
...
}
Is setFile an override that you are calling from the parent class constructor? In that case: The parent class constructor runs before the useful part fo the child constructor. So setFile is called from the parent class constructor, and then control is returned to the child class constructor which you have nulling out that variable.
The instance field initialisers and instance initialisers are actually part of constructors, after the possibly implicit call to super (but not if they call this()). I believe C sharp inserts instance initialisers before the call to super (but they can't reference this).
What to do: Avoiding inheritance is always good. In particular avoid protected variables and calling overridable methods from constructors. Keep constructors simple. And don't add = null to instance fields.
Resolved with following code:
private static FileResourceManager frm;
public void writeOut(E event) throws IOException {
...
if (frm == null) {
frm = new FileResourceManager(fileName, tempDir, false, loggerFacade);
}
Object txId = null;
try {
...
}
catch (Exception e) {
...
}
}
fileName is initialized(not null) within writeOut() method.
Not very gracefully,but looks like simplest solution in my case.
You have to call the setFile() method in the parent class.
Assuming that your "parent class" is the SomeClass class, overwrite the default constructor there:
public Someclass(String fileName) {
this.fileName = fileName;
}