My question is simple. I'm trying to make a set of java.net.URLs that are public static final, so that any class can access them from any context, as these URLs won't change during runtime. However, when I try to create them, I get a compiler error telling me that I must catch or declare thrown a java.net.MalformedURLException, but that is impossible outside a method. Is there any way to circumvent such a constructor that throws a non-java.lang Throwable?
Some dummy code below to visualize my problem:
public class Main
{
public static final java.net.URL STATIC_URL = new java.net.URL("http://example.com/");
public static void main(String[] args)
{
GUI gui = new GUI();
gui.setVisible(true);
}
}
public class GUI extends java.awt.Window
{
public GUI()
{
add(new java.awt.Label(Main.STATIC_URL.toString()));
}
}
If you try to compile this, it will tell you that you can't because of line 3. Hence my question.
An "alternative" which I'd prefer to #HosamAly method:
private static final java.net.URL STATIC_URL = makeUrl("http://www.example.com");
public static java.net.URL makeUrl(String urlString) {
try {
return new java.net.URL(urlString);
} catch (java.net.MalformedURLException e) {
return null; //Or rethrow an unchecked exception
}
}
Use a static initializer:
public class Main {
private static final java.net.URL STATIC_URL;
static {
java.net.URL temp;
try {
temp = new java.net.URL("http://www.example.com");
} catch (java.net.MalformedURLException e) {
temp = null;
}
STATIC_URL = temp;
}
}
Note: The usage of a temporary variable is required to avoid a compilation error about assigning to the final static field twice. If the field is not final, the assignment could be done directly.
If you're sure you want to hardwire a URL. Are you sure? java.net.URL is one of the most comprehensively broken classes in the JDK. In regards to use as a "constant", there is DNS lookup involved and it uses a mutable static (albeit one guarded by a security check, if you have a SecurityManager installed).
If it's just one, a static initialiser should be fine.
private static final java.net.URL STATIC_URL;
static {
try {
STATIC_URL = new java.net.URL("http://example.com/");
} catch (java.net.MalformedException exc) {
throw new Error(exc);
}
}
(Note, you can't qualify the static field name with the class name.)
Note: You really do not want a null - throw an error of some sort and stop the class loading. I've made the constant private as it really isn't the sort of thing you want dependencies on.
If you have lots, then a method for the common code and assignment at the site of the definition is appropriate.
private static final java.net.URL STATIC_URL = constantURL("http://example.com/");
private static URL constantURL(String str) {
try {
return new java.net.URL("http://example.com/");
} catch (java.net.MalformedException exc) {
throw new Error(exc);
}
}
Again, no nulls!
The only way I got this to compile is by removing final and using the static initializer block.
/**
*
*/
package com.neurologic.example;
import java.net.MalformedURLException;
import java.net.URL;
/**
* #author The Elite Gentleman
* #since 06 December 2011
*
*/
public class StaticUrlTest {
public static URL url = null;
static {
try {
url = new URL("http://www.google.com");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Related
Background: I use the Java class InitialDirContext to access LDAP directories. Unfortunately, it does not implement interface AutoCloseable, so it cannot be used in try-with-resources blocks.
Here is the original code I wrote: (inspired by this answer)
final Properties props = new Properties();
// Populate 'props' here.
final InitialDirContext context = new InitialDirContext(props);
Exception e0 = null;
try {
// use 'context' here
}
catch (Exception e) {
// Only save a reference to the exception.
e0 = e;
// Why re-throw?
// If finally block does not throw, this exception must be thrown.
throw e;
}
finally {
try {
context.close();
}
catch (Exception e2) {
if (null != e0) {
e0.addSuppressed(e2);
// No need to re-throw 'e0' here. It was (re-)thrown above.
}
else {
throw e2;
}
}
}
Is this a safe, correct, and equivalent replacement?
try (final AutoCloseable dummy = () -> context.close()) {
// use 'context' here
}
I think the answer is yes, but I want to confirm. I tried Googling for this pattern, but I found nothing. It is so simple! Thus, I am suspicious it may not be correct.
Edit: I just found this answer with a similar pattern.
As explained in the other answer you linked to, it is not strictly equivalent because you have to either catch or throw Exception from AutoCloseable.close() and you must be sure not to do anything with context after the try block because it is not out of scope as if InitialDirContext directly implemented AutoCloseable. Still I agree with others that this workaround is quite nice.
Of course, you could also extend InitialDirContext and make it implement AutoCloseable directly or (for final classes) use a delegator pattern and wrap the target object.
package de.scrum_master.stackoverflow;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import java.util.Hashtable;
import java.util.Properties;
public class TryWithResourcesAutoCloseableWrapper {
public static void main(String[] args) throws NamingException {
final Properties props = new Properties();
props.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
variant1(props);
variant2(props);
variant3(props);
}
public static void variant1(Properties props) throws NamingException {
final InitialDirContext context = new InitialDirContext(props);
try (final AutoCloseable dummy = context::close) {
lookupMX(context);
}
catch (NamingException ne) {
throw ne;
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void variant2(Properties props) throws NamingException {
final InitialDirContext context = new InitialDirContext(props);
try (final MyCloseable dummy = context::close) {
lookupMX(context);
}
}
public static void variant3(Properties props) throws NamingException {
try (final MyInitialDirContext context = new MyInitialDirContext(props)) {
lookupMX(context);
}
}
private static void lookupMX(InitialDirContext context) throws NamingException {
System.out.println(context.getAttributes("scrum-master.de", new String[] { "MX" }));
}
public interface MyCloseable extends AutoCloseable {
void close() throws NamingException;
}
public static class MyInitialDirContext extends InitialDirContext implements AutoCloseable {
public MyInitialDirContext(Hashtable<?, ?> environment) throws NamingException {
super(environment);
}
}
}
A few more thoughts about how to use these workarounds:
Both variant1 and variant2 come at the cost of dummy objects which inside the try block you will never use, unless you cast them to InitialDirContext first. Instead, you could directly use the outer context objects, of course, which is also what you suggested.
In variant3 the auto-closable context object directly has the correct (sub-)type, so you can actually work with it seamlessly without casting or dummy object. This comes at the cost of a special subclass.
I am trying to call the URL retrieving method inside the static block, the Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError.
I am trying to get a WSDL url from the config file. this configuration data stored DB.
static
{
URL url = null;
WebServiceException e = null;
try
{
url = getVertexConfiguration();
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
}
private static URL getVertexConfiguration() throws MalformedURLException
{
try {
configuration = configurationDAO.getByRefName("tax/vertex",
SecureSession.getUser().getDataDomain() != null ?
SecureSession.getUser().getDataDomain() : "app.cantata");
} catch (B2BTransactionFailed b2BTransactionFailed) {
}
Map<String, DynamicAttribute> vertexTaxConfig = configuration.getConfigs();
vertexWsdlUrl = vertexTaxConfig.get("vertexWsdlUrl").getValue().toString();
return new URL(vertexWsdlUrl);
}
}
I am getting static block, the Instantiation of bean failed; nested exception is java.lang.ExceptionInInitializerError.
The root cause is that static block is the earliest step when setup as class level initialization which even ahead of constructor calling. That is to say your dependency in static block such as that configurationDAO has not initialized yet. You shouldn't use static for it. Instead, you should make it a normal Instance method.
Why should you even try this? I think your configurationDAO is not even initialized at the moment you're trying to access it.
As we discussed in the comments, I would definitely recommend you, author, to inject your dependencies correctly, like:
#Service
public class ConfigurationService {
private final ConfigurationDao configurationDao;
private URL url;
public ConfigurationService(ConfigurationDao configurationDao) {
this.configurationDao = configurationDao;
}
#PostConstruct
private void init() {
// your stuff here
}
}
Or you can even initialize your url in constructor:
#Service
public class ConfigurationService {
private final ConfigurationDao configurationDao;
private final URL url;
public ConfigurationService(ConfigurationDao configurationDao) {
this.configurationDao = configurationDao;
this.url = getVertexConfiguration();
}
private URL getVertexConfiguration() {
// your stuff here
}
}
You get ExceptioninInitializerBlock if there are some errors in the static initializer block. You handle only MalformedURLException, however, there are may be others.
You should add another catch for all exceptions and see what happens there.
static {
URL url = null;
WebServiceException e = null;
try {
url = getVertexConfiguration();
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
} catch (Exception e) {
//real problem
}
}
That exception is a relaying mechanism for an error which occurred while running a static initializer. The exception should have a cause, which will describe the actual error. Per your description, above, there look to be three layers of exception: Error reporting from bean initialization, the ExceptionInInitializer exception, then the cause of the ExceptionInInitializer exception. The exception processing should display all three layers, but might not, which will make uncovering the base exception more difficult.
From the ExceptionInInitializer javaDoc:
* Signals that an unexpected exception has occurred in a static initializer.
* An <code>ExceptionInInitializerError</code> is thrown to indicate that an
* exception occurred during evaluation of a static initializer or the
* initializer for a static variable.
As a fall-back, you could put inside getVertexConfiguration a try-catch on Throwable, and have the catch block print out the stack:
private static URL getVertexConfiguration() throws MalformedURLException {
try {
// Code omitted
} catch ( Throwable th ) {
th.printStackTrace();
return null;
}
}
I'm newbie in reflection. Is there any way to detect where is an specific method invoked? For example:
public class MyClass {
public static void method(){
//DO SOMETHING
}
}
public class Test {
public test(){
MyClass.method();
}
}
public class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Method method = MyClass.class.getDeclaredMethod("method");
Class classWhereMethodIsInvoked = obtainClassWhereMethodIsInvoked(method);
}
public Class obtainClassWhereMethodIsInvoked(Method method) {
//here I want to search one class that invoke that method, in this case Test.class
}
}
is something like this possible or I am going crazy?
As mentioned in the comments, Apache BCEL is suitable for your problem. Such libraries are often particularly used for determining compile-time information such as method usage and control flow analysis from the generated bytecode, and such information are difficult, if not impossible, to retrieve using reflection. If you use the BCEL solution, you probably no longer require a custom annotation processor.
But since you already seem to be using a custom annotation processor, the whole point of it is to be able to process annotations in the source files. So one way is to define a custom annotation that marks a method being called, and have the custom processor read these annotations to know which classes call which methods:
#CallerClass("MyClass.method")
public class Test {
public test() {
MyClass.method();
}
}
In the above (trivial) example, a custom CallerClass annotation marks that a class calls the method specified in the annotation's element inside parentheses. The annotation processor can read this annotation and construct the caller information.
Yes it doable if you really want it. You can use the classLoader to search through the class path and scan for the method name through all the class files. Below is a very simplistic example to show that it is doable. In the example below I find usage of the "println" method being used in this class. Essentially you can just broaden the scope from one file in my example to all the class files.
public class SearchClasses {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
// InputStream is = SearchClasses.class.getClassLoader().getResourceAsStream("resources.SearchClasses.class");
InputStream is = new FileInputStream(new File("build/classes/resources/SearchClasses.class"));
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains("println")) {
System.out.print("println found");
found = true;
break;
}
}
if (!found) {
System.out.print("println NOT found");
}
}
public static void testMethod() {
System.out.println("testing");
}
}
In my IDE I had to use the FileInputStream to access the class file I was searching in.... but if you are searching through jar files then you can use the classLoader instead. You would need mechanism to search through all of the class path... this is not impossible but I left it our for brevity.
EDIT: Here is an attempt to get it working completely.. searches all files in class path for your method.
public class SearchClasses {
/**
* #param args the command line arguments
* #throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
printAllFileWithMethod("println");
}
public static void printAllFileWithMethod(String methodName) throws FileNotFoundException, IOException {
Enumeration<URL> roots = SearchClasses.class.getClassLoader().getResources("");
List<File> allClassFiles = new ArrayList<>();
while (roots.hasMoreElements()) {
File root = new File(roots.nextElement().getPath());
allClassFiles.addAll(getFilesInDirectoryWithSuffix(root, "class"));
}
for (File classFile : allClassFiles) {
InputStream is = new FileInputStream(classFile);
boolean found = false;
Scanner scanner = new Scanner(is);
while (scanner.hasNext()) {
if (scanner.nextLine().contains(methodName)) {
System.out.print(methodName + " found in " + classFile.getName() + "\n");
found = true;
break;
}
}
}
}
public static void testMethod() {
System.out.println("testing");
}
static List<File> getFilesInDirectoryWithSuffix(File dir, String suffix) {
List<File> foundFiles = new ArrayList<>();
if (!dir.isDirectory()) {
return foundFiles;
}
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
foundFiles.addAll(getFilesInDirectoryWithSuffix(file, suffix));
} else {
String name = file.getName();
if (name.endsWith(suffix)) {
foundFiles.add(file);
}
}
}
return foundFiles;
}
}
You could define your own mechanism. Use a Map to store the caller of each method :
public static Map<Method, List<String>> callStack = new HashMap<Method, List<String>>();
public static void registerCaller(Method m)
{
List<String> callers = callStack.get(m);
if (callers == null)
{
callers = new ArrayList<String>();
callStack.put(m, callers);
}
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
callers.add(stackTraceElements[3].getClassName());
}
The target class :
class MyClass
{
public static void method()
{
registerCaller(new Object(){}.getClass().getEnclosingMethod());
// DO SOMETHING
}
}
Some caller classes :
package the.package.of;
class Test
{
public void test()
{
MyClass.method();
}
}
class Foo
{
public void bar()
{
MyClass.method();
}
}
And finally, the test :
new Test().test();
new Foo().bar();
Method method = MyClass.class.getDeclaredMethod("method");
for (String clazz : callStack.get(method))
{
System.out.println(clazz);
}
Prints :
the.package.of.Test
the.package.of.Foo
Well, if you use Eclipse as an IDE, you can find the complete call hierarchy via "Open Call Hierarchy" function. This will find all usages of your method in any open Eclipse projects.
However, if you want to find out during runtime programmatically, then you need to integrate some library, that can statically analyze the bytecode of your classpath for use of your method.
You can obtain stack trace right inside the test method:
public class Test {
public void test() {
System.out.println(getCallerClass());
}
public static String getCallerClass() {
for (StackTraceElement e: Thread.currentThread().getStackTrace()) {
if (!"java.lang.Thread".equals(e.getClassName()) && !e.getClassName().equals(Test.class.getName()))
return e.getClassName();
}
return null;
}
}
If a class is loaded multiple times, do its static-members get initialized multiple times?
How do I check for that?
If there are different classloaders involved, then they will be completely separate classes, with separate static fields etc - and each will be initialized separately.
(The simplest way to diagnose this is just to log when you get initialized, of course...)
static {
// Log initialization
}
The code inside static block is executed only once: the first time you make an object of that class or the first time you access a static member of that class (even if you never make an object of that class). This mean its invoked when the class loader loads the class to memory. So its per class loader. If you have multiple class loaders each one will have its own copy of the classes so static block will be invoked by each class loaders. To test this you can put a Sysout in a static block an try and load it using a custom class loader. In the below example the static block will be executed twice. One by the system class loader when we run the static main method and then by our custom class loader.
package sample;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Sample {
static {
System.out.println("Entered Static Block!!");
}
public static void main(String[] args) {
CustomClassLoader loader = new CustomClassLoader();
try {
Class<?> c = loader.findClass("sample.Sample");
Object o = c.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
class CustomClassLoader extends ClassLoader {
private Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
#Override
public String toString() {
return CustomClassLoader.class.getName();
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (classes.containsKey(name)) {
return classes.get(name);
}
byte[] classData;
try {
classData = loadClassData(name);
} catch (IOException e) {
throw new ClassNotFoundException("Class [" + name
+ "] could not be found", e);
}
Class<?> c = defineClass(name, classData, 0, classData.length);
resolveClass(c);
classes.put(name, c);
return c;
}
private byte[] loadClassData(String name) throws IOException {
BufferedInputStream in = new BufferedInputStream(
ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ ".class"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
int i;
while ((i = in.read()) != -1) {
out.write(i);
}
in.close();
byte[] classData = out.toByteArray();
out.close();
return classData;
}
}
The following actions do not cause a class to be loaded:
Referring to a static final primitive field that is known at compile time.
classLoader.getResource(className.replace('.', '/') + ".class")
The following cause a class to be loaded (i.e., the .class file is parsed, and a Class<?> object is created):
Any line of code that refers to the class symbolically e.g. Foo.class
Class.forName(String, false, ClassLoader)
ClassLoader.loadClass(String)
Loading a subclass or array of the class, or initializing a class whose code or method signatures refer to the class.
The following cause a class to be initialized (i.e., the static blocks are executed):
Constructing a new instance
Calling a static method
Getting or setting a static field that is not a compile-time constant.
Class.forName(String, true, ClassLoader) and Class.forName(String)
If you do initialize the class from multiple ClassLoaders, the static blocks are indeed executed multiple times. For example, the following code:
import java.net.URL;
import java.net.URLClassLoader;
public class InitializeClassMultipleTimes {
static class Foo {
static {
System.out.format(" %s initialized by %s%n", Foo.class.getSimpleName(), Foo.class.getClassLoader());
}
public static void foo() {}
}
private static Class<Foo> loadClass() {
System.out.println("Loading class.");
// Load the .class file. This will fail if the class file is gone or has
// the wrong file format.
return Foo.class;
}
private static void initializeClass(Class<?> innerClass) {
System.out.println("Initializing class");
try {
Class.forName(innerClass.getName(), true, innerClass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
}
public static void main(String... argv) throws ClassNotFoundException {
Class<Foo> fooClass = loadClass();
initializeClass(fooClass);
URLClassLoader myClassLoader = ((URLClassLoader) InitializeClassMultipleTimes.class.getClassLoader());
URL[] urls = myClassLoader.getURLs();
for (int i = 0; i < 2; i++) {
URLClassLoader newClassLoader = new URLClassLoader(urls, null); // parent=bootstrap
System.out.format("%nLoading class using another class loader%n", Foo.class.getSimpleName());
Class<?> fooClassAgain = Class.forName(fooClass.getName(), false, newClassLoader);
initializeClass(fooClassAgain);
}
}
}
produces the following output. Note that you can also run it under strace -f -e file to verify when the .class files are read.
Loading class.
Initializing class
Foo initialized by sun.misc.Launcher$AppClassLoader#73d16e93
Loading class using another class loader
Initializing class
Foo initialized by java.net.URLClassLoader#15db9742
Loading class using another class loader
Initializing class
Foo initialized by java.net.URLClassLoader#7852e922
I'm not sure if I'm asking this right, as I'm attempting to teach myself Java. I have a class which contains my main method, and within this class are several subclasses that need access to my user settings using java.util.Properties. I have to create the properties object in every subclass in order to make it work, and I can't reference the object using configFilePath, it must be null. I'm wondering if I can create this public object within the parent class, so I don't need to create it in all of its subclasses? Here is my code, I'm really not sure I'm doing this right although it works.
public class Frame1 extends JFrame {
Settings config = new Settings(); //this is the object I want to reference within subclasses
class Update extends SwingWorker<Integer, Void> { //first subclass
#Override
protected Integer doInBackground() throws Exception {
Settings config = new Settings(configFilePath); //yet I have to create the object within every subclass, this time an argument is required.
String templateDir = config.getProperty("templatedir");
String writePath = config.getProperty("outputdir");
//do some logic code, not required for my question
}
#Override
protected void done() {
Update2 update2 = new Update2();
update2.execute(); //start the next subclass which also needs access to Settings(configFilePath)
}
}
}
public class Settings extends JFrame {
String configFilePath = "C:/path/to/settings.properties";
Properties properties = new Properties();
public Settings(String configFilePath) throws IOException {
this.configFilePath = configFilePath;
FileInputStream fis = null;
try {
fis = new FileInputStream(configFilePath);
properties.load(fis);
} catch (FileNotFoundException e) {
setDefaults();
} finally {
if (fis != null) {
fis.close();
}
}
}
}
I'm not sure if I'm doing this right or not, it seems to work but seems to be rather redundant having to create the config object every time I need to access my user settings. I hope this hasn't been asked before, and if it has please link me, as I could not find it.
You can create the Setting class as a Singleton pattern, here is one example:
public class Settings extends JFrame{
String configFilePath = "C:/path/to/settings.properties";
Properties properties = new Properties();
private static Settings instance;
public static Settings getInstance(){
if(instance==null){
instance = new Setting();
}
return instance;
}
private Settings() throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(configFilePath);
properties.load(fis);
} catch (FileNotFoundException e) {
setDefaults();
} finally {
if (fis != null) {
fis.close();
}
}
}
}
Usage in any other class of your system:
Settings.getInstance().getProperty("...");
From Update you can use Frame1.this to access the this of Frame1 (because Update is an inner class of Frame1).
Then to access config you can use Frame1.this.config.
Here is a working example:
public class PrefixerFactory {
private String prefix; // Used by Prefixer
public PrefixerFactory(String prefix) {
this.prefix = prefix;
}
public Prefixer createPrefixer() {
return new Prefixer();
}
public class Prefixer { // Inner class
public String addPrefix(String value) {
// Using "prefix" from PrefixerFactory
return PrefixerFactory.this.prefix + value;
}
}
public static void main(String[] args) {
Prefixer helloPrefixer = new PrefixerFactory("Hello ").createPrefixer();
Prefixer goodbyePrefixer = new PrefixerFactory("Good bye ").createPrefixer();
System.out.println(helloPrefixer.addPrefix("world")); // Hello world
System.out.println(goodbyePrefixer.addPrefix("world")); // Good bye world
}
}