我正在尝试使用@ApplicationScoped
@ManagedBean
调用和计划任务,每2秒将一些属性加载到我的JSF应用程序中。由于某种原因无效。
请参阅我遵循的步骤。
我做的第一件事是创建一个每2秒从文件系统加载的类:
@ManagedBean
@ApplicationScoped
public class ProppertyReader {
@PostConstruct
public void init(){
SystemReader systemReader = new SystemReader();
systemReader.schedule();
}
private class SystemReader {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private Logger LOGGER = Logger.getLogger(ProppertyReader.class.getName());
public void schedule(){
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
Properties properties = loadProperties();
LOGGER.info("Loaded property enabled:" + properties.getProperty("enabled"));
}
}, 0L, 2L, TimeUnit.SECONDS);
}
private Properties loadProperties() {
try {
Properties properties = new Properties();
properties.load(new FileInputStream("~/Desktop/propertiesRepo/example.properties"));
return properties;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
然后我去另一个bean,我尝试使用该属性:
@ManagedBean
@SessionScoped
public class SomeBean {
//...
private Properties properties = new Properties();
private boolean enabled = new Boolean(properties.getProperty("enabled"));
//...
public boolean isEnabled() {
return enabled;
}
}
当我尝试在JSF if语句中使用#{someBean.enabled}
来使用某个bean来显示或隐藏组件时,取决于该值,似乎不起作用:
<c:if test="#{someBean.enabled}">
<h1>Works!</h1>
</c:if>
我没有错,有什么想法吗?
更新 我看到了我的错误,使用了属性类。我现在正在尝试创建那些没有被处理的属性,所以我清理了一些代码,但是当应用程序启动时我得到一个NullPointer。
我将属性读者分为两类:
@ManagedBean
@ApplicationScoped
public class ProppertyReader {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private SystemReader systemReader = new SystemReader();
public static Properties appProperties;
@PostConstruct
public void init(){
schedule();
}
private void schedule(){
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
appProperties = systemReader.loadProperties();
}
}, 0L, 2L, TimeUnit.SECONDS);
}
}
这是我从系统中读取的地方:
public class SystemReader {
public Properties loadProperties() {
try {
Properties properties = new Properties();
properties.load(new FileInputStream("~/Desktop/propertiesRepo/example.properties"));
return properties;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
我现在称之为:
@ManagedBean
@SessionScoped
public class SomeBean {
private boolean enabled = new Boolean(ProppertyReader.appProperties.getProperty("enabled"));
//...
目前我收到了NullPointer异常,我想我已经接近了。
答案 0 :(得分:2)
这不是Java的工作方式。
为了实现您的目标,您应该将属性文件保存为应用程序作用域bean的实例变量,并且每次都重新加载其内容,而不是每次都重新创建和删除它(!!)。您应该在会话作用域bean中也不创建属性类的完全独立的实例,而是实际使用的应用程序作用域中保存的那个。
这是重写:
@ManagedBean
@ApplicationScoped
public class PropertiesHolder {
private static final String PATH = "~/Desktop/propertiesRepo/example.properties";
private Properties properties;
private ScheduledExecutorService scheduler;
@PostConstruct
public void init() {
properties = new Properties();
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
properties.load(new FileInputStream(PATH));
} catch (IOException e) {
throw new RuntimeException("Failed to load properties", e);
}
}
}, 0L, 2L, TimeUnit.SECONDS);
}
@PreDestroy
public void destroy() {
scheduler.shutdownNow();
}
public String getProperty(String key) {
return properties.getProperty(key);
}
}
请注意,我还添加了一个关闭调度程序的@PreDestroy
,否则您可能会在每次重启服务器时泄漏线程,直到Java运行时环境用尽线程。
以下是如何在会话范围bean中使用它,以防您想要获取最新值:
@ManagedBean
@SessionScoped
public class SomeBean {
@ManagedProperty("#{propertiesHolder}")
private PropertiesHolder propertiesHolder;
public void setPropertiesHolder(PropertiesHolder propertiesHolder) {
this.propertiesHolder = propertiesHolder;
}
public boolean isEnabled() {
return new Boolean(propertiesHolder.getProperty("enabled"));
}
}
请注意,在bean的实例化时不会获取该属性,否则您将在每次getter调用时仅获取bean实例化时的值,并且永远不会在同一会话中的后续请求中获取更新值。
更重要的是,该值本质上是请求作用域,因此会话范围只是保存值的错误范围。把它变成一个请求范围的bean:
@ManagedBean
@RequestScoped
public class SomeBean {
@ManagedProperty("#{propertiesHolder.getProperty('enabled')}")
private boolean enabled;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}