Is it possible to lazily instantiate a final field?
The following code does not compile:
public class Test{
private final Connection conn;
public Connection getConnection(){
if(conn==null){
conn = new Connection();
}
return conn;
}
}
Is there an alternative?
No. The point of a final field is that it's set once, during construction, and will never change thereafter. How could the compiler or the VM know anything useful about conn in your case? How would it know that only that property should be able to set it, and not some other method?
Perhaps if you explained what you want the semantics to be, we could come up with an alterative. You could potentially have a "provider" interface representing a way to fetch a value, and then a MemoizingProvider which proxies to another provider, but only once, caching the value otherwise. That wouldn't be able to have a final field for the cached value either, but at least it would only be in one place.
Here's one way you can do it using Memoisation (with Callables):
Class Memo:
public class Memo<T> {
private T result;
private final Callable<T> callable;
private boolean established;
public Memo(final Callable<T> callable) {
this.callable = callable;
}
public T get() {
if (!established) {
try {
result = callable.call();
established = true;
}
catch (Exception e) {
throw new RuntimeException("Failed to get value of memo", e);
}
}
return result;
}
}
Now we can create a final conn!
private final Memo<Connection> conn = new Memo<Connection>(
new Callable<Connection>() {
public Connection call() throws Exception {
return new Connection();
}
});
public Connection getConnection() {
return conn.get();
}
Source
dhiller's answer is the classic double checked locking bug, do not use.
As Jon Skeet said, no, there isn't.
Interpreting your code sample you may want to do something like this:
public class Test{
private final Object mutex = new Object(); // No public locking
private Connection conn;
public Connection getConnection(){
if(conn==null){
synchronized (mutex) {
if(conn==null){
conn = new Connection();
}
}
}
return conn;
}
}
As a side note, it's possible to change a final field. At least instance fields. You just need some reflection:
import java.lang.reflect.Field;
public class LazyFinalField {
private final String finalField = null;
public static void main(String[] args) throws Exception {
LazyFinalField o = new LazyFinalField();
System.out.println("Original Value = " + o.finalField);
Field finalField = LazyFinalField.class.getDeclaredField("finalField");
finalField.setAccessible(true);
finalField.set(o, "Hello World");
System.out.println("New Value = " + o.finalField);
}
}
Original Value = null
New Value = Hello World
Related
I am rewriting exceptions from an old system and everything was working, but I needed make BAD_REQUEST configurable.
private static final String BAD_REQUEST = "BDRQ";
I tried to just put ConfigProperty, but it doesn't work.
import javax.ws.rs.core.Response.Status;
import org.eclipse.microprofile.config.inject.ConfigProperty;
public class SXClientException extends RuntimeException {
#ConfigProperty(name = "greeting.error", defaultValue = "BDRQ")
public String BAD_REQUEST;
private final RuntimeException runtimeException;
public SXClientException(RuntimeException e) {
super(e);
this.runtimeException = e;
}
public Status getStatus() {
if (BAD_REQUEST.equals(runtimeException.getMessage())) {
return Status.BAD_REQUEST;
}
return Status.INTERNAL_SERVER_ERROR;
}
// ...
}
It probably doesn't work since I make them without any CDI.
catch (LegacyOMException e) {
throw new SXClientException(e);
}
I would prefer to avoid creating another bean (and passing the value) just to compare one String. Any idea how can I read a configuration value for a static-ish value?
you can use org.eclipse.microprofile.config.ConfigProvider.
Works for both static and non static members.
public static final String BAD_REQUEST = ConfigProvider.getConfig().getValue("greeting.error",String.class);
public final String BAD_REQUEST = ConfigProvider.getConfig().getValue("greeting.error",String.class);
use follow method:
Properties properties = new Properties();
InputStream inputStream = this.getClass().getResourceAsStream("/menu.properties");
properties.load(inputStream );
System.out.println(properties.getProperty("a"));
I have a situation where I read data from a YAML file that is important for the application because it is used in several classes. Here is my code:
public class CredentialsReader {
private UserCredentials credentials;
private boolean isReading = false;
public CredentialsReader() {
}
public void readCredentials() {
Runnable readerTask = new Runnable() {
#Override
public void run() {
isReading = true;
parseCredentials();
isReading = false;
System.err.println("Parsed credentials");
}
};
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(readerTask, 0, 60, TimeUnit.SECONDS);
}
private void parseCredentials() {
final File f = new File("/home/dev/IdeaProjects/server/src/main/resources/credentials.yaml");
try {
UserCredentials userCredentials = new ObjectMapper().readValue(f, UserCredentials.class);
this.credentials = userCredentials;
System.out.println(this.credentials.getUsername() + ", " + this.credentials.getPassword());
} catch (IOException e) {
e.printStackTrace();
}
}
public UserCredentials getCredentials() { return this.credentials; }
}
As you see, I read the data every minute and my question is:
Can I delay the return value of getCredentials, so when the method is called I check if isReading is true and then delay the return so I can guarantee that a caller will always get the actual state of the yaml file?
I think there are appropriate locks for similar situations, but this seems like synchronize is sufficient.
synchronized private void parseCredentials() {...}
synchronized public UserCredentials getCredentials() { ... }
By declaring those methods synchronized only one thread at a time will be able to enter the method, essentially a barrier. That means that parseCredentials could have to wait for getCredentials, but getCredentials is so trivially fast you'll never notice.
That will synchronize on an instance of CredentialReader, so if you use more than one, you might want to synchronize on something else. As mentioned it the comments it is better to synchronize on a private object rather than the instance itself. It is a small change:
public class CredentialsReader {
private UserCredentials credentials;
private boolean isReading = false;
final private Object lock = new Object();
...
Then remove the synchronize from the method signature and add a synchronize call in the body.
private void parseCredentials() {
synchronize(lock){
//original code goes here.
}
}
Also, isReading should be volatile.
I do not suggest to do it manually, you could use a CountDownLatch with init value 1 provided in jdk.
You can let the readers calls await, and let the writer calls countDown once data is prepared.
So the reader could always get fully initialized data.
Still struggling with properly making a cacheBean. I think I want the bean to be a singleton, from what I have read. Will only need
one instance of it. Use it to get often used keywords and so on.
http://blog.defrog.nl/2013/02/prefered-way-for-referencing-beans-from.html
I used this pattern to make my CacheBean (and used a utility method).
If I make this a managedBean by putting it into Faces-config, then I can easily get the value of models
<xp:text escape="true" id="computedField1"
value="#{CacheBean.models}"></xp:text>
The JSF takes care of instantiating the bean for me.
But I don't want it to reload the same values (like models) over and over. I thought that to get that to happen I needed to make
a POJO and grab the currentInstance of the bean, as in the url.
However, when I made this change (taking the bean out of the faces-config file, I cannot seem to get a handle on the properties.
This won't even compile:
<xp:text escape="true" id="computedField1"
value="#{Cache.getCurrentInstance().models}">
</xp:text>
What am I doing wrong?
================================
package com.scoular.cache;
import java.io.Serializable;
import org.openntf.domino.xsp.XspOpenLogUtil;
import com.scoular.Utils;
public class CacheBean implements Serializable {
private static final long serialVersionUID = -2665922853615670023L;
public static final String BEAN_NAME = "CacheBean";
private String pcDataDBpath;
private Vector<Object> models = new Vector<Object>();
public CacheBean() {
initConfigData();
}
private void initConfigData() {
try {
loadModels();
loadDBPaths();
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
// Getters and Setters
public static CacheBean getInstance(String beanName) {
return (CacheBean) Utils.getVariableValue(beanName);
}
public static CacheBean getInstance() {
return getInstance(BEAN_NAME);
}
public String getPcDataDBpath() {
return pcDataDBpath;
}
public void setPcDataDBpath(String pcDataDBpath) {
this.pcDataDBpath = pcDataDBpath;
}
public void loadDBPaths() {
Session session = Factory.getSession();
Database tmpDB = session.getCurrentDatabase();
pcAppDBpath = (tmpDB.getServer() + "!!" + "scoApps\\PC\\PCApp.nsf");
pcDataDBpath = (tmpDB.getServer() + "!!" + "scoApps\\PC\\PCData.nsf");
compDirDBpath = (tmpDB.getServer() + "!!" + "compdir.nsf");
}
public void loadModels() {
try {
Session session = Factory.getSession();
Database tmpDB = session.getCurrentDatabase();
Database PCDataDB = session.getDatabase(tmpDB.getServer(), "scoApps\\PC\\PCData.nsf");
ViewNavigator vn = PCDataDB.getView("dbLookupModels").createViewNav();
ViewEntry entry = vn.getFirst();
while (entry != null) {
Vector<Object> thisCat = entry.getColumnValues();
if (entry.isCategory()) {
String thisCatString = thisCat.elementAt(0).toString();
models.addElement(thisCatString);
}
entry = vn.getNextCategory();
}
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
p
ackage com.scoular;
import javax.faces.context.FacesContext;
public class Utils {
public static Object getVariableValue(String varName) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getVariableResolver().resolveVariable(context, varName);
}
}
When the bean has the right scope you can access the bean directly if is created.
private static final String BEAN_NAME = "CacheBean";
//access to the bean
public static CacheBean get() {
return (CacheBean) JSFUtil.resolveVariable(BEAN_NAME);
}
//in my JSFUtil class I have the method
public static Object resolveVariable(String variable) {
return FacesContext.getCurrentInstance().getApplication().getVariableResolver().resolveVariable(FacesContext.getCurrentInstance(), variable);
}
so in a Java Class you can call
CacheBean.get().models
in EL you can use
CacheBean.models
I can tell you why it's not compiling at least.
value="#{Cache.getCurrentInstance().models}"
That's EL. So there should not be a get or a (). You want
value="#{Cache.currentInstance.models}"
And check your var name as I thought you were using CacheBean and not Cache.
First some context: all the code pasted below is within another class declared as public class TheClass extends SomeProprietaryClass. I cannot declare these classes in another file for various reasons... And log messages are in French. And I'm a "final happy" kind of programmer. Which is at the core of the problem here...
Now, the code... (probably too much of it -- stripping on demand to only keep the relevant parts)
A custom Exception:
private static final class BreadCrumbException
extends Exception
{
private BreadCrumbException(final String message)
{
super(message);
}
private BreadCrumbException(final String message, final Throwable cause)
{
super(message, cause);
}
}
An enum for "materializing" the visibility of a breadcrumb element:
private enum Visibility
{
MAINPAGE("R"),
MENU("M"),
BREADCRUMB("A"),
COMMERCIAL("C");
private static final Map<String, Visibility> reverseMap
= new HashMap<String, Visibility>();
private static final String characterClass;
static {
final StringBuilder sb = new StringBuilder("[");
for (final Visibility v: values()) {
reverseMap.put(v.flag, v);
sb.append(v.flag);
}
sb.append("]");
characterClass = sb.toString();
}
private final String flag;
Visibility(final String flag)
{
this.flag = flag;
}
static EnumSet<Visibility> fromBC(final String element)
{
final EnumSet<Visibility> result = EnumSet.noneOf(Visibility.class);
for (final String s: reverseMap.keySet())
if (element.contains(s))
result.add(reverseMap.get(s));
return result;
}
static String asCharacterClass()
{
return characterClass;
}
static String asString(final EnumSet<Visibility> set)
{
final StringBuilder sb = new StringBuilder();
for (final Visibility v: set)
sb.append(v.flag);
return sb.toString();
}
#Override
public String toString()
{
return flag;
}
}
A breadcrumb element:
private static class BreadCrumbElement
{
private static final Pattern p
= Pattern.compile(String.format("(%s+)(\\d+)",
Visibility.asCharacterClass()));
private final String element;
private final String menuID;
private final EnumSet<Visibility> visibility;
BreadCrumbElement(final String element)
{
final Matcher m = p.matcher(element);
if (!m.matches())
throw new IllegalArgumentException("Élément de fil d'ariane invalide: " + element);
this.element = element;
visibility = EnumSet.copyOf(Visibility.fromBC(m.group(1)));
menuID = m.group(2);
}
public boolean visibleFrom(final Visibility v)
{
return visibility.contains(v);
}
#Override
public boolean equals(final Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
final BreadCrumbElement that = (BreadCrumbElement) o;
return element.equals(that.element);
}
#Override
public int hashCode()
{
return element.hashCode();
}
#Override
public String toString()
{
return element;
}
public String getMenuID()
{
return menuID;
}
}
A breadcrumb:
private static class BreadCrumb
implements Iterable<BreadCrumbElement>
{
private static final BreadCrumb EMPTY = new BreadCrumb();
private final List<BreadCrumbElement> elements
= new LinkedList<BreadCrumbElement>();
private String bc;
BreadCrumb(final String bc)
throws BreadCrumbException
{
final Set<BreadCrumbElement> set = new HashSet<BreadCrumbElement>();
BreadCrumbElement e;
for (final String element: bc.split("\\s+")) {
e = new BreadCrumbElement(element);
if (!set.add(e))
throw new BreadCrumbException("Élément dupliqué "
+ "dans le fil d'Ariane : " + element);
elements.add(e);
}
if (elements.isEmpty())
throw new BreadCrumbException("Fil d'ariane vide!");
if (!elements.get(0).visibleFrom(Visibility.MAINPAGE))
throw new BreadCrumbException("Le fil d'Ariane ne "
+ "commence pas à l'accueil : " + bc);
set.clear();
this.bc = bc;
}
private BreadCrumb()
{
}
BreadCrumb reverse()
{
final BreadCrumb ret = new BreadCrumb();
ret.elements.addAll(elements);
Collections.reverse(ret.elements);
ret.bc = StringUtils.join(ret.elements, " ");
return ret;
}
public Iterator<BreadCrumbElement> iterator()
{
return elements.iterator();
}
#Override
public String toString()
{
return bc;
}
}
The interface to a breadcrumb renderer:
public interface BreadCrumbRender
{
List<CTObjectBean> getBreadCrumb()
throws Throwable;
String getTopCategory();
String getMenuRoot();
String getContext();
}
The implementation of the interface above which is the source of my problems:
private class CategoryBreadCrumbRender
implements BreadCrumbRender
{
private final BreadCrumb bc;
private final CTObject object;
CategoryBreadCrumbRender(final CTObject object)
{
this.object = object;
final String property;
// FIELD_BC is declared as a private static final String earlier on.
// logger is also a private static final Logger
try {
property = object.getProperty(FIELD_BC);
} catch (Throwable throwable) {
logger.fatal("Impossible d'obtenir le champ " + FIELD_BC
+ " de l'objet", throwable);
bc = BreadCrumb.EMPTY;
return;
}
try {
bc = new BreadCrumb(property);
} catch (BreadCrumbException e) {
logger.fatal("Impossible d'obtenir le fil d'Ariane", e);
bc = BreadCrumb.EMPTY; // <-- HERE
}
}
// ....
At the point marked // <-- HERE above, Intellij IDEA, which I use, and javac (1.6.0.29) both tell me that Variable bc might already have been assigned to, which is considered an error (and indeed, the code does not compile).
Trouble is, I do not understand why... My reasoning is the following:
in the first try/catch block (and yes, .getProperty() does throw Throwable), when an exception is caught, bc gets assigned to successfully, and then I return, so far so good;
in the second try/catch block, the constructor may fail, in which case I assign an empty breadcrumb, so it should be OK, even though bc is final: the assignment doesn't happen (?) in the try block but happens in the catch block instead...
Except no, it doesn't. As both IDEA and javac disagree with me, they are certainly right. But why?
(and also, BreadCrumb.EMPTY is declared private static final in the class, I wonder how come I can access it at all... Subsidiary question)
EDIT: there is a known bug with the final keyword (here, thanks to #MiladNaseri for linking to it), however it should be noted that in this bug, variable v is only ever assigned in catch blocks -- but in the code above, I assign it in try blocks and only assign it in catch blocks if an exception is thrown. Also, it should be noted that the error only occurs in the second catch block.
Okay, suppose that in the first try block, when doing property = object.getProperty(FIELD_BC); an exception occurs. So, JVM will enter the catch block, and initialize bc along the way.
Then in the second try block, also an exception occurs, resulting in BreadCrumb.EMPTY being assigned to bc, effectively overriding its original value.
Now, that is how bc might have already been initialized. I hope you see where I'm coming from.
Since the JAVAC analysis engine does not draw a distinction between one or many statements inside the try block, it does not see your case any different than the below:
try {
bc = null;
String x = null;
System.out.println(x.toString());
} catch (Throwable e) {
bc = null;
}
In which case, bc will be assigned twice. In other words, JAVAC won't care that where the source of the Throwable lies, it only cares that it can be there, and that bc might undergo a successful assignment in that try block.
I don't think the analysis is deep enough to really understand that there is only one statement in the try block, and the diagnostic is issued no matter what, so that's why you're seeing it in your case.
Try this instead:
BreadCrumb tmp = null;
try {
tmp = new BreadCrumb(property);
} catch (BreadCrumbException e) {
logger.fatal("Impossible d'obtenir le fil d'Ariane", e);
tmp = BreadCrumb.EMPTY;
}
bc = tmp;
Is there any way to access caller-scoped variables from an anonymous inner class in Java?
Here's the sample code to understand what I need:
public Long getNumber(final String type, final String refNumber, final Long year) throws ServiceException {
Long result = null;
try {
Session session = PersistenceHelper.getSession();
session.doWork(new Work() {
public void execute(Connection conn) throws SQLException {
CallableStatement st = conn.prepareCall("{ CALL PACKAGE.procedure(?, ?, ?, ?) }");
st.setString(1, type);
st.setString(2, refNumber);
st.setLong(3, year);
st.registerOutParameter(4, OracleTypes.NUMBER);
st.execute();
result = st.getLong(4) ;
}
});
} catch (Exception e) {
log.error(e);
}
return result;
}
The code is in a DAO service class. Obviously it doesn't compile, because it asks that result be final, if it is -- it doesn't compile because I try to modify a final var. I'm bound to JDK5. Other than dropping the doWork() altogether, is there a way to set the result value from within doWork()?
Java doesn't know that doWork is going to be synchronous and that the stack frame that result is in will still be there. You need to alter something that isn't in the stack.
I think this would work
final Long[] result = new Long[1];
and then
result[0] = st.getLong(4);
in execute(). At the end, you need to return result[0];
You might want to make a class because you don't like how it looks to use an array here, but this is the basic idea.
This situation arises a lot in Java, and the cleanest way to handle it is with a simple value container class. It's the same type thing as the array approach, but it's cleaner IMO.
public class ValContainer<T> {
private T val;
public ValContainer() {
}
public ValContainer(T v) {
this.val = v;
}
public T getVal() {
return val;
}
public void setVal(T val) {
this.val = val;
}
}
You need a 'container' to hold your value. You, however, do not have to create a container class. You may use classes in the java.util.concurrent.atomic package. They provide an immutable wrapper for a value along with a set and a get method. You have AtomicInteger, AtomicBoolean, AtomicReference<V> (for your objects) e.t.c
In the outer method:
final AtomicLong resultHolder = new AtomicLong();
In the anonymous inner class method
long result = getMyLongValue();
resultHolder.set(result);
Later in your outer method
return resultHolder.get();
Here's an example.
public Long getNumber() {
final AtomicLong resultHolder = new AtomicLong();
Session session = new Session();
session.doWork(new Work() {
public void execute() {
//Inside anonymous inner class
long result = getMyLongValue();
resultHolder.set(result);
}
});
return resultHolder.get(); //Returns the value of result
}
Long is immutable. If you use a mutable class, holding a long value, you can change the value. For example:
public class Main {
public static void main( String[] args ) throws Exception {
Main a = new Main();
System.out.println( a.getNumber() );
}
public void doWork( Work work ) {
work.doWork();
}
public Long getNumber() {
final LongHolder result = new LongHolder();
doWork( new Work() {
public void doWork() {
result.value = 1L;
}
} );
return result.value;
}
private static class LongHolder {
public Long value;
}
private static abstract class Work {
public abstract void doWork();
}
}
If the containing class is MyClass -->
MyClass.this.variable = value;
Do not remember if this would work with a private variable (I think it would work).
Only works for attributes of the class (class variable). Does not work for method local variables. In JSE 7 probably there will be closures to do that kind of thing.
Anonymous classes/methods are not closures - this is exactly the difference.
The problem is that doWork() could create a new thread to call execute() and getNumber() could return before the result is set - and even more problematically: where should execute() write the result when the stack frame that contains the variable is gone? Languages with closures have to introduce a mechanism to keep such variables alive outside their original scope (or ensure that the closure is not executed in a separate thread).
A workaround:
Long[] result = new Long[1];
...
result[0] = st.getLong(4) ;
...
return result[0];
The standard solution to this is to return a value. See, for instance, ye olde java.security.AccessController.doPrivileged.
So the code would look something like this:
public Long getNumber(
final String type, final String refNumber, final Long year
) throws ServiceException {
try {
Session session = PersistenceHelper.getSession();
return session.doWork(new Work<Long>() {
public Long execute(Connection conn) throws SQLException {
CallableStatement st = conn.prepareCall("{ CALL PACKAGE.procedure(?, ?, ?, ?) }");
try {
st.setString(1, type);
st.setString(2, refNumber);
st.setLong(3, year);
st.registerOutParameter(4, OracleTypes.NUMBER);
st.execute();
return st.getLong(4);
} finally {
st.close();
}
}
});
} catch (Exception e) {
throw ServiceException(e);
}
}
(Also fixed the potential resource leak, and returning null for any error.)
Update: So apparently Work is from a third-party library and can't be altered. So I suggest not using it, at least isolate your application from so that you are not using it directly. Something like:
public interface WithConnection<T> {
T execute(Connection connnection) throws SQLException;
}
public class SessionWrapper {
private final Session session;
public SessionWrapper(Session session) {
session = nonnull(session);
}
public <T> T withConnection(final WithConnection<T> task) throws Service Exception {
nonnull(task);
return new Work() {
T result;
{
session.doWork(this);
}
public void execute(Connection connection) throws SQLException {
result = task.execute(connection);
}
}.result;
}
}
As of Hibernate 4, the method Session#doReturningWork(ReturningWork<T> work) will return the return val from the inner method:
public Long getNumber(final String type, final String refNumber, final Long year) throws ServiceException {
try {
Session session = PersistenceHelper.getSession();
return session.doReturningWork(conn -> {
CallableStatement st = conn.prepareCall("{ CALL PACKAGE.procedure(?, ?, ?, ?) }");
st.setString(1, type);
st.setString(2, refNumber);
st.setLong(3, year);
st.registerOutParameter(4, OracleTypes.NUMBER);
st.execute();
return st.getLong(4);
});
} catch (Exception e) {
log.error(e);
}
return null;
}
(Cleaned up using a Java 8 lambda)
Using AtomicLong helped me in a very similar situation and the code looked clean.
// Create a new final AtomicLong variable with the initial value 0.
final AtomicLong YOUR_VARIABLE = new AtomicLong(0);
...
// set long value to the variable within inner class
YOUR_VARIABLE.set(LONG_VALUE);
...
// get the value even outside the inner class
YOUR_VARIABLE.get();