I am trying to load a class dynamically through reflection by using the method Class.forname("classname") as given in below code.
Class<? extends Layout> layoutClassName;
try {
layoutClassName = (Class<? extends Layout>) Class.forName(site.getSiteLayout());
} catch (ClassNotFoundException e) {
layoutClassName= DefaultLayout.class;
}
I am trying to load a class dynamically if it is defined by the logged in user (db configuration), otherwise provide the default implementation.
This works fine, but after a statistical analysis we found that approximately 80% of the times default implementation is used.
This means approximately 80% of times an Exception object is created. Since creating exception objects is heavy, I would like to avoid it and use some other logic to Identify if a class is present or not.
Please suggest.
PS: I am not looking for any significant performance boost, I am just trying to clean up my existing code.
I don't know if there's a convenient way to check if class exists without throwing ClassNotFoundException that will work for general case.
Handling ClassNotFoundException seems appropriate and clear in this situation. There are several earlier questions that all recommend to handle exception: 1, 2, 3
But if you really want to:
load layouts dynamically (so, you can't avoid reflection);
load layouts by unrestricted class name (if you don't have configuration, can't build defined and relatively stable list of all layout classes);
minimize ClassNotFoundException for some reason.
then I can suggest to cache layout classes. If you don't have a large number of different layouts something like this might work:
private HashMap<String, Class<? extends List>> layoutsByName = new HashMap<>();
public Class<? extends Layout> getLayout(String name) {
Class<? extends Layout> layoutClass = layoutsByName.get(name);
if(layoutClass!=null) {
return layoutClass;
}
layoutClass = getLayoutUsingReflection(name);
layoutsByName.put(name, layoutClass);
return layoutClass;
}
private Class<? extends Layout> getLayoutUsingReflection(String name) {
try {
return (Class<? extends Layout>) Class.forName(name);
} catch (ClassNotFoundException e) {
return DefaultLayout.class;
}
}
This way you won't check for the same layout twice.
As you said...
I am trying to load a class dynamically if it is defined in configuration
Is the 'configuration' is mentiond in some file.
I hope you can get hold of the configuration file(or the configuration status), and create the object for the class only and only if it is mentioned to do so. If not apply the default implementation.
If you cant access the configuration i fear there is no other way as far as i know.
Related
I want to design an API which reads a large text file, extracts the relevant info and returns a list of Foo objects like this:
interface FooService {
Optional<Foo> getFoo(Bar bar);
}
The format of the text file and the way it is parsed is always the same. The only thing that can vary is the location of the file, i.e. it could be a file on the local system or an URL. So I created an AbstractFooService:
class AbstractFooService implements FooService {
Map<Bar, Foo> registry;
AbstractFooService(InputStream is) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
registry = reader.lines()
.map(l -> l.split(';'))
.map(a -> new Foo(a[0]), a[1]))
.collect(Collectors.groupingBy(...));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
Optional<Foo> getFoo(Bar bar) {
return Optional.ofNullable(registry.get(bar));
}
}
Concrete implementations would just call the super constructor with an InputStream:
class UrlFooService extends AbstractFooService {
UrlFooService(String url) {
super(createStream(url));
}
private static InputStream createStream(final String url) {
try {
return new URL(string).openStream();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
Is that a sound API design or is there a 'better' way to achieve my goal? I.e. is it smart to call the super constructor with an InputStream or would it be better to have a separate load() method that opens the stream when needed?
I don't see why you need that abstract base class there. Preferring composition over inheritance; I think the more reasonable solution would be to have:
public class FooServiceImpl implements FooService {
...
And then clients such as
public class UrlFooService implements FooService {
private final FooService delegatee;
public UrlFooService(URL url) {
delegate = new FooServiceImpl(url.openStream())
...
#Override
Optional<Foo> getFoo(Bar bar) { return delegatee.getFoo(bar); }
Inheritance couples your concrete service classes with that parent class; I would prefer to avoid, by using this simple "delegatee" mechanism.
Please note: I also changed the ctor of the UrlSerivce to take a URL. You already have the types there, so why bother to call new yourself? That just means that your UrlService would have to deal with all the things that could go wrong there!
There's a couple of challenges with your question here and I would start by breaking down the problem a little differently.
As #sisyphus said, watch out for those things you're doing in the constructor. A constructor really should be focused on just creating a "valid object" and nothing more. Many good ideas from #GhostCat too.
Instead think of modeling the problem as follows:
Create an interface that represents the API for your service. In this case if you want it to be "getFoo()" then great. Consider what you would want to pass (is it really the file or a URL or path). Since you said it was a big file, it might not be a great idea to instantiate a big object in memory that you're going to be parsing again into a useful format. You'll definitely pay the price in garbage collection.
Next you should think of separating out the "finding" of the file - or opening the stream with the parsing logic. There are plenty of exceptions that can occur when simply trying to open the file - from it not being found, to not having permissions, to having too many open files (ulimit).
When it comes to parsing, I would suggest that you consider to get really clear on what you are parsing and for what. If this is a real-world problem, 'stable formats' are always subject to change - especially when it comes to tolerating 'invalid' formats - like the existence of other non-printable characters or an unexpected EOF. There will be a lot of demands to handle things gracefully and also a need to understand the stats of what was parsed, what had errors and how to handle that.
My 2 cents.
I'm writing a taglet-based library, which, when the first taglet is found, loads some configuration (starting with a text-file filled with properties).
The configuration object is being held statically directly in each Taglet object, but it seems that they are being garbage collected and then respawned by javadoc.exe in a subsequent taglet, causing the configuration to be reloaded over and over again.
Am I understanding this correctly, and is there a way around it? How can I make it so that configuration loads only once?
Thanks.
UPDATE
As mentioned in the comments, no, this does not impact performance or correctness. Since javadoc.exe is used by a single person on a single machine, performance is not much of an issue.
However, it clutters up the log each time configuration is loaded (at least five times per javadoc.exe run), and it does some moderately-heavy stuff, including loading package-lists from multiple websites, loading and parsing template files, and a bunch of other file processing. If there is any way to prevent this from happening many times in a single JavaDoc run, I would like to.
I have no experience with multithreading, so I may have this completely wrong...but what about setting up a daemon thread that does nothing but load configuration and then hold it all statically? This answer suggests that an I/O-based daemon thread is a bad idea, but I think it means ones that do ongoing I/O.
(I'm not sure if this would be something that should be manually started and stopped, or if its possible for the process itself to start the daemon thread... I'm going to read the concurrency chapters in Bloch's Effective Java...)
If two classes loaded by different ClassLoaders without parent-child relationship have to share data, the normal Java language constructs do not work. If you can get hands on a Class object or an instance, you have to access them via Reflection, even if it is the same class just loaded by different loaders.
Further, passing the data via heap variables won’t work as both ClassLoaders establish their own “namespace” hence a class loaded by two different loader creating two distinct Class objects will have their distinct copies of static variables as well. You need a storage which is independent from your own classes.
Thankfully, that storage exists in the context of Taglets. The register method receives a Map containing all previously registered Taglets. But besides the fact that you have to use Reflection rather than instanceof or Class comparison to find your “friend” Taglets, there is another obstacle: the JavaDoc implementation will wrap your Taglets within another object.
Putting it all together, you could implement the find-and-share logic into a base class of your Taglets and let the register method of the Taglets call it:
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;
public abstract class Base
{
static Properties CONFIG=new Properties();
static void initProperties(Map<?, ?> fromTagManager) {
String className=Base.class.getName();
for(Object o: fromTagManager.values()) {
o=extractTagLet(o);
if(o==null) continue;
for(Class<?> cl=o.getClass(); cl!=null; cl=cl.getSuperclass())
if(cl.getName().equals(className) && initFromPrevious(cl)) return;
}
// not found, first initialization
try {
CONFIG.load(Base.class.getResourceAsStream("config.properties"));
} catch(IOException ex) {
throw new ExceptionInInitializerError(ex);
}
}
private static Object extractTagLet(Object o) {
if(!o.getClass().getSimpleName().equals("LegacyTaglet"))
return o;
try {
Field f=o.getClass().getDeclaredField("legacyTaglet");
f.setAccessible(true);
return f.get(o);
} catch(NoSuchFieldException | IllegalAccessException ex) {
ex.printStackTrace();
}
return null;
}
private static boolean initFromPrevious(Class<?> cl) {
// this is the same class but loaded via a different ClassLoader
try {
Field f=cl.getDeclaredField("CONFIG");
f.setAccessible(true);
CONFIG=(Properties)f.get(null);
return true;
} catch(NoSuchFieldException | IllegalAccessException ex) {
return false;
}
}
}
Then a Taglet will be implemented like this:
import java.util.Map;
import com.sun.javadoc.Tag;
import com.sun.tools.doclets.Taglet;
public class ExampleTaglet extends Base implements Taglet {
#SuppressWarnings("unchecked")
public static void register(#SuppressWarnings("rawtypes") Map map) {
initProperties(map);
final ExampleTaglet taglet = new ExampleTaglet();
final String name = taglet.getName();
map.remove(name);// must ensure new Taglet is the last one (LinkedHashMap)
map.put(name, taglet);
}
// implement the Taglet interface below…
I'm looking for a way to provide multiple pieces of information for exceptions back to end users. The obvious solution of extending Exception ends up with text distributed throughput the code, for example
throw new MyException("Bad data", "The data you entered is incorrect", "http://www.example.com/moreinfo/baddata");
and this quickly becomes unworkable.
I then looked at a catalogue approach but that's too centralized and requires jumping around from one file to another every time an exception is thrown. I'm now considering a hybrid approach with a static ErrorInfoMap class that contains mappings from a key to the more detailed information. Each class then has a static section that contains its own error mappings, so using the class which throws the above exception as an example I'd change it to:
throw new MyException("Bad data");
and at the bottom of the class there would be something like:
static {
ErrorInfoMap.put("Bad data", new ErrorInfo("The data you entered is incorrect", "http://www.example.com/moreinfo/baddata"));
// Information for other exceptions thrown by this class goes here
}
which allows an exception handler to fetch the additional information if required. Is this a good way of solving this issue, or is there a better way to handle this?
I'm not sure what exactly you mean by "the catalog approach" (could you provide a reference or more detailed description?) but from the information you provided, it's not clear to me how a static ErrorInfoMap avoids the problem of being "too centralized and [requiring] jumping around from one file to another every time an exception is thrown".
To me there are several options, depending on exactly what you need to accomplish:
Create a root class, ExceptionTemplate that extends Exception and does whatever repeatable behavior you'd like all your exceptions to do. Formatted toString() methods are a good example. Depending on your exact goals, you might like having your exceptions implement a builder pattern, like so:
throw new BadDataException("Supplied data is not valid")
.expected("a positive integer")
.referenceUrl("http://www.example.com/moreinfo/baddata");
Avoid stringly-typed solutions where an enum or subclass will do. If you don't need to define new exception types at runtime (and if you do, that should be a red flag that there's something deeper wrong with your design) and have an enum that contains all the necessary information to construct your exceptions:
public class EnumException extends Exception {
private EnumException() {} // prevent objects from being instantiated elsewhere
public enum Type {
BAD_DATA("Bad Data","Supplied data is not valid", "http://www.example.com/moreinfo/baddata"),
MISSING_DATA("Missing Data","Required data not found", "http://www.example.com/moreinfo/missingdata");
Type(String title, String genericMessage, String url) {
// Store input
}
public EnumException exception() {
// construct your exception
return new EnumException();
}
}
}
Which can be called with something like:
// note no `new` - the exception is returned by the enum
throw EnumException.Type.BAD_DATA.exception().expected("a positive integer");
This has the advantages of ensuring compile-time type safety, while still giving you the flexibility to define different types of Exceptions in one place.
Create lots of exceptions. I'm still not totally sure what objection you have to just creating a bunch of exceptions. You're looking for ways to "provide additional information" but claim that "the obvious solution of extending Exception ends up with text distributed throughput the code". This shouldn't be the case. Every subclass of Exception should hold all the necessary information except what can only be provided at construction time. Therefore there should be minimal "text distributed throughout the code" as any boiler-plate / reusable strings should be in the Exception class, and nowhere else.
public class DocumentedException extends Exception
{
private String title;
private String genericMessage;
private String detailedMessage;
private String url;
// Generally avoid this long constructor, and define subclasses that only need detailedMessage
public DocumentedException(String t, String g, String d, String u) {
super(g + " - " + d); // sets the getMessage() return value to something sane
title = t;
genericMessage = g;
detailedMessage = d;
url = u;
}
public String toString() {
return title.toUpperCase()+"\n"+
genericMessage+"\n"+
detailedMessage+"\n"+
"More info on this error: "+url+"\n";
}
public static class BadData extends DocumentedException {
public BadData(String details) {
super("Bad Data", "Supplied data is not valid", details, "http://www.example.com/moreinfo/baddata");
}
}
public static class MissingData extends DocumentedException {
public MissingData(String details) {
super("Missing Data", "Required data not found", details, "http://www.example.com/moreinfo/missingdata");
}
}
}
Which you can then call simply with:
throw new DocumentedException.BadData("Username cannot contain whitespace");
Of course, if you expected to need to warn against username errors regularly, you could create an additional class:
public static class BadUsername extends BadData {
public BadUsername() {
super("Usernames can only contain letters, numbers, and underscores");
}
}
The goal, again, is to explicitly define a hierarchy of exceptions that handle all cases you anticipate needing to deal with, such that you avoid repeatedly defining the same strings throughout your application. I personally like the group-exceptions-into-inner-classes pattern I used above, it lets you be very explicit with your errors without creating hundreds of silly stub java files you need to look through constantly. I would say that every major package should have an associated exception-holding class that defines all necessary exceptions for that package.
An alternative to your hybrid approach would be to put the error mapping in the exception itself. When MyException is initialised with Bad data add in the ErrorInfo that you've shown, but also provide a range of constructors for MyException that allows you to override or supplement the default definition of what Bad data means.
You could always have "MyException" as the superclass and have the specific types of errors as subtypes of that. In terms of error messages, you can use static constants on the subtypes to store the different types of errors.
E.g
Exception
-> MyException
-> BadDataException
-> InvalidUserException
etc.
Would be throw like so:
throw new BadDataException(BadDataException.DATA_TOO_LONG);
I am working on a project that has been through multiple hands with a sometimes rushed development. Over time the message.properties file has become out of sync with the jsps that use it. Now I don't know which properties are used and which aren't. Is there a tool (eclipse plugin perhaps) that can root out dead messages?
The problem is that messages may be accessed by JSP or Java, and resource names may be constructed rather than literal strings.
Simple grepping may be able to identify "obvious" resource access. The other solution, a resource lookup mechanism that tracks what's used, is only semi-reliable as well since code paths may determine which resources are used, and unless every path is traveled, you may miss some.
A combination of the two will catch most everything (over time).
Alternatively you can hide the functionality of ResourceBundle behind another façade ResourceBundle, which should generally pipe all calls to original one, but add logging and/or statistics collection on the top.
The example can be as following:
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.ResourceBundle;
public class WrapResourceBundle {
static class LoggingResourceBundle extends ResourceBundle {
private Collection<String> usedKeys = new HashSet<String>();
public LoggingResourceBundle(ResourceBundle parentResourceBundle) {
setParent(parentResourceBundle);
}
#Override
protected Object handleGetObject(String key) {
Object value = parent.getObject(key);
if (value != null) {
usedKeys.add(key);
return value;
}
return null;
}
#Override
public Enumeration<String> getKeys() {
return EMPTY_ENUMERATOR;
}
public Collection<String> getUsedKeys() {
return usedKeys;
}
private static EmptyEnumerator EMPTY_ENUMERATOR = new EmptyEnumerator();
private static class EmptyEnumerator implements Enumeration<String> {
EmptyEnumerator() {
}
public boolean hasMoreElements() {
return false;
}
public String nextElement() {
throw new NoSuchElementException("Empty Enumerator");
}
}
}
public static void main(String[] args) {
LoggingResourceBundle bundle = new LoggingResourceBundle(ResourceBundle.getBundle("test"));
bundle.getString("key1");
System.out.println("Used keys: " + bundle.getUsedKeys());
}
}
Considering that some of your keys are run-time generated, I don't think you'll ever be able to find a tool to validate which keys are in use and which ones are not.
Given the problem you posed, I would probably write an AOP aspect which wraps the MessageSource.getMessage() implementation and log all the requested codes that are being retrieved from the resource bundle. Given that MessageSource is an interface, you would need to know the implementation that you are using, but I suspect that you must know that already.
Given that you would be writing the aspect yourself, you can create a format that is easily correlated against your resource bundle and once you are confident that it contains all the keys required, it becomes a trivial task to compare the two files and eliminate any superfluous lines.
If you really want to be thorough about this, if you already have Spring configured for annotation scan, you could even package up your aspect as its own jar (or .class) and drop it in a production WEB-INF/lib (WEB-INF/classes) folder, restart the webapp and let it run for a while. The great thing about annotations is that it can all be self contained. Once you are sure that you have accumulated enough data you just delete the jar (.class) and you're good to go.
I know that at least two of the major java IDEs can offer this functionality.
IntelliJ IDEA has a (disabled, by default) Inspection that you can
use to do this:
go to Settings -> Inspections -> Properties files -> ... and enable
the 'Unused property'
..Only problem I had was that it didn't pick up some usages of the property from a custom tag library I had written, which I was using in a few JSPs.
Eclipse also has something like this ( http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftasks-202.htm ) but I haven't really exhausted the how well it works.
From the perspective of a cross application/applet java accessibility service, how would you link to a package but only optionally execute an action based on existence/availability of a package (being already loaded) at runtime?
I think what I'm interested in here is a way to resolve the class identity crisis but rather than the issue being between 2 apps sharing objects, being a service loaded at a higher level of the class loaders.
It seems like reflection is the way to go, but I am not sure how or if I can implement a derived class this way. I need to add a specific listener derived from the specific optional classes, I can load the listener using the applet class loader but the internals still fail. Say you wanted to add an JInternalFrameListener, but Swing wasn't guaranteed to be available, using reflection you can find the method to add the listener, but how can you create and have the frame listener work if it cannot find any of the related classes because they can't be found in the base classloader! Do I need to create a thread and use setContextClassLoader to the classloader that knows about swing so that I can get the class to be loaded reliably? simply trying to set the class loader on my existing thread didn't seem to work.
Earlier description of issues
Sorry, I'm not quite sure what to ask or how to make this clear, so it rambles on a bit.
Say a class uses some feature of another, but the other class may not always be available - say finding the website from JNLP if this is a JNLP app.
At one stage I thought that simply compiling against JNLP would mean that my class would not load unless JNLP was available, and so to identify this optional section I simply wrapped a try{} catch( NoClassDefFoundError ) around it.
Later something changed (perhaps changing jdk or ?? I don't recall) and it seemed that I should also use a try{} catch( ClassNotFoundException ).
Now I wanted to extend this idea to other optional features, but it doesn't seem to work consistently.
Say I wanted to add some feature to do something more advanced in a JRE1.6 runtime using the same jar and classes as I run in a JRE1.3, or say I want to handle some controls in a specific gui toolkit which may not always be used like SWT or oracle.forms.
Is there some way of doing this more reliably? It just seems wrong to cause an exception and catch it to ignore it all the time.
The current issue comes down to being able to compile against oracle.forms but then the accessibility component installed in ext is unable to access the oracle.forms classes even though objects from the oracle.forms package have been created. If I throw the frmall.jar into the ext directory to test then the accessibility component works up to the point that the whole lot gets flakey because of the different versions of the same package.
I seem to be caught up on an issue with the class loader not being the right one or something (??). How do I find the right one?
Edit:
The answers so far are kindof interesting but not quite getting me where I want to be.
In the case of the gui components I currently compile in the form of a factory something like...
import oracle.forms.ui.*;
import java.awt.*;
static public IComponentNode newNode( INode parent, Component component ) {
System.out.println( component.getClass().toString() );
try{
if( component instanceof FormDesktopContainer )
... does stuff here like return new FormDesktopNode( parent, (FormDesktopContainer) component )
} catch ( NoClassDefFoundError a ) {
System.out.println( a.getMessage() );
}
where it prints out class oracle.forms.ui.FormDesktopContainer and then throws and exception on the instanceof call with NoClassDefFound thus printing out oracle/forms/ui/FormDesktopContainer
So how can it have an instance of a class yet not be able to find it?
How about this? messy, but it ought to work:
public boolean exists(String className){
try {
Class.forName(className);
return true;
}
catch (ClassNotFoundException){
return false;
}
}
You can check the availability of a class by calling
ClassLoader.getSystemClassLoader().loadClass("my.package.MyClass")
if it throws a ClassNotFoundException, it's not available. If you get the Class object, it is. You can then choose behaviour based on whether or not the class is available.
I suggest compiling the majority of your code against your minimum target. Have code that uses particular optional libraries clearly separated, but dependent upon the bulk of your code. Dynamically load the code that uses optional libraries once. The main class should do something that checks for the presence of the required library/version in its static initialiser.
In the case of JNLP, your JNLP main class load the JNLP dependent code statically.
(Note that attempting to catch class loading related exceptions from normally linked code is unreliable.)
getSystemClass loader was not useful for this purpose as there where multiple possible class loaders to interact with based on which applet the given window was in. The accessibility components being loaded at a more base class loader cannot see the applet specific classes.
To interact with the objects reflection does the job, though it does add so much more to maintain.
// statically linking would be
return component.getText();
// dynamically is
try {
return (String)component.getClass().getMethod("getText", new Class [] {}).invoke(component, new Object [] {});
} catch (Throwable e) {
e.printStackTrace();
}
The trickier bit is in writing a class derived from an interface that is not directly accessible, using the Proxy service allows this to be accomplished, providing the proxy service the applet specific class loader and the dynamically loaded class for the interface.
public void addListener(Container parent) {
if (parent == null) { return; }
if ("oracle.forms".equals(parent.getClass().getName())) {
// Using the class loader of the provided object in the applet
// get the "class" of the interface you want to implement
Class desktopListenerClass = Class.forName( "oracle.DesktopListener"
, true, parent.getClass().getClassLoader());
// Ask the proxy to create an instance of the class,
// providing your implementation through the InvocationHandler::invoke
Object desktopListener = Proxy.newProxyInstance(
parent.getClass().getClassLoader()
, new Class[] { desktopListenerClass }, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if ("functionName".equals(method.getName())) {
// do stuff
}
return null;
}
});
// do something with your new object
Method addDesktopListener = parent.getClass().getMethod("");
addDesktopListener.invoke(parent, desktopListener);
}
}
examples cut down to show general method