-1

I have a project with sorting algorithms, I need to use a properties file to set the algorithm that I will use, my properties file looks like this:

sorter=metodosOrdenamiento.QuickSorterImpl

where "metodosOrdenamiento" is the package and "QuickSorterImpl" is my class. I'm trying this:

public static Sorter getInstance() throws IllegalAccessException, InstantiationException {
        Properties properties = new Properties();
        Class<?> myClass = null;
        try {
            properties.load(new FileInputStream("java_3/MiFactory.properties"));
            myClass = Class.forName(properties.get("sorter").toString());

        } catch (IOException | ClassNotFoundException e) {
            System.out.println("No se pudo obtener la clase");
            e.printStackTrace();
        }
        assert myClass != null;
        return (Sorter)myClass.newInstance();
    }

But it produces a "ClassNotFoundException", Which is the correct way to instantiate the class from the properties file?

Daniel Lopez
  • 63
  • 1
  • 6
  • 2
    First, determine which part is broken. Does `myClass = Class.forName("metodosOrdenamiento.QuickSorterImpl");` work? If so, then your `properties` aren't loading correctly (which is my guess). – Elliott Frisch Apr 27 '21 at 00:58
  • There are two possible issues here: A) your classpath setup is wrong B) the class name you are using is wrong. So: look at the stack trace. It tells you the exact name of the class to load. If the name is valid: then your class path is wrong. If the name is not valid, then fix that part. – GhostCat Apr 27 '21 at 09:47

2 Answers2

0

You probably haven't set your classpath correctly - as per @Elliott Frisch comment, and you are using deprecated API Class.newInstance(). Use Class.getConstructor().newInstance() IF there is a no-args constructor.

It is much easier to debug if you test both the constructor and classpath by hardwiring the class:

public static Sorter getInstance() throws ReflectiveOperationException {
    Class<?> myClass = metodosOrdenamiento.QuickSorterImpl.class;
    assert myClass != null;
    return (Sorter)myClass.getConstructor().newInstance();
}

If that works, switch to load the classname from properties file:

private static Properties getProperties() {
    String name = "java_3/MiFactory.properties";
    try(var in = new FileInputStream(name))
    {
        Properties properties = new Properties();
        properties.load(in);
        return properties;
    } catch (IOException io)  {
        throw new UncheckedIOException("Could not find: "+name,io);
    }
}
public static Sorter getInstance() throws ReflectiveOperationException {
    Class<?> myClass = Class.forName(getProperties().getProperty("sorter"));
    assert myClass != null;
    return (Sorter)myClass.getConstructor().newInstance();
}
DuncG
  • 12,137
  • 2
  • 21
  • 33
  • 1
    Note that the usage of `assert` requires the `-ea` flag to be set at application start else it will be ignored by the JVM – Roman Vottner Apr 27 '21 at 09:35
-2

You can try to use following code

Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath));
Roman Vottner
  • 12,213
  • 5
  • 46
  • 63
xindanding
  • 39
  • 3
  • 1
    Your answer tells readers how to correctly read a properties file from the classpath. How does that answer a question that asks about loading classes dynamically? – GhostCat Apr 27 '21 at 09:46
  • Your answer assumes that Daniel is having problems loading the properties file, when we actually don't know yet for sure. Maybe the class he wants to load is not yet on the classpath, as shipped with a different JAR that is not added to the CP on application start and not loaded afterwards via a custom classloader, or the fully-qualified class name is not correct either. Maybe his properties file is also not directly on the classpath but in a dedicated configuration location like `/etc` on *nix environments or the like – Roman Vottner Apr 27 '21 at 09:46