Getting Java beans that were set in a try method - java

I am setting a java bean from within a try method. A text file is being read and the text that is read is used to set the java bean.
public class mainDisplay extends JPanel{
private imageDisplay id;
public mainDisplay()
{
String path;
while (1==1) {
try {
FileInputStream roadMap = new FileInputStream("C:\\Users\\Public\\Desktop\\write.txt"); //path to the text file generated
DataInputStream route = new DataInputStream(roadMap); //importing the data from the text file
BufferedReader readMe = new BufferedReader(new InputStreamReader(route));
pathOfspeed = readMe.readLine();
// id = new imageDisplay(path);
Constants.getInstance().getBean().setPath(path);
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
} catch (Exception e) {
System.err.println("error:" + e.getMessage());
}
System.out.println(Constants.getInstance().getBean().getPath());
}
}
That is the code from the text file reader and the code that sets the Bean.
Here is the code from the bean class:
public class Paths implements java.io.Serializable{
public String url;
public Paths(){}
public void setPath(String name){this.url=name;}
public String getPath(){return url;}
}
I then have my constants class
public class Constants {
private static Constants instance;
private Paths bean;
private Constants() {
bean=new Paths();
}
public static synchronized Constants getInstance() {
if (instance == null) {
instance = new Constants();
}
return instance;
}
public Paths getBean(){
return bean;
}
public Paths setBean(Paths p){
bean = p;
return p;
}
}
My problem then occurs when I try to get that Bean from another class:
String imageUrl=Constants.getInstance().getBean().getPath();
public test () {
System.out.println(imageUrl);
}
I get null every single time. The file reader needs to be constant as the line in the text file is changing about every minute and I need that passed to another class that uses it.
Could someone give me some suggestions as to what to do next?
Thanks

The problem is in your Constants class.
Every time you do:
Constants.Bean
it returns a newly created Path class which of course contains a null url variable which is returned to your getPath method.
You should use a Singleton for your Constants class.
Modify your Constants class:
public class Constants {
private static Constants instance;
private Paths bean;
private Constants() {
bean=new Paths();
}
public static synchronized Constants getInstance() {
if (instance == null) {
instance = new Constants();
}
return instance;
}
public Paths getBean(){
return bean;
}
public Paths setBean(Paths p){
bean = p;
}
}
Write to the Paths variable using:
Constants.getInstance().getBean().setPath("your path");
read the Paths variable;
Constants.getInstance().getBean().getPath();

Related

Guice, Type Conversion When Getting Values from Properties

The following Guice module binds a property file to the #Named annotation.
import com.google.inject.AbstractModule;
import com.google.inject.name.Names;
// Omitted: other imports
public class ExampleModule extends AbstractModule {
#Override
protected void configure() {
Names.bindProperties(binder(), getProperties());
}
private Properties getProperties() {
// Omitted: return the application.properties file
}
}
I can now inject properties directly into my classes.
public class Example {
#Inject
#Named("com.example.title")
private String title;
#Inject
#Named("com.example.panel-height")
private int panelHeight;
}
The values read from a properties file are strings but, as you can see in the example above, Guice is capable of doing type conversion for int fields.
Now, given the property com.example.background-color=0x333333 I would like to able to get the same type conversion for an arbitrary class, like:
public class Example {
#Inject
#Named("com.example.background-color")
private Color color;
}
Let's say that the Color class contains a static method decode() and I can obtain a new Color instance by calling Color.decode("0x333333").
How can I configure Guice to do this automatically and behind the scenes for me?
I found a solution by myself looking into the Guice sources, although I have to say it's not the prettiest (more on this later on).
First of all, we need to create a TypeConverter.
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeConverter;
// Omitted: other imports
public class ColorTypeConverter implements TypeConverter {
#Override
public Object convert(String value, TypeLiteral<?> toType) {
if (!toType.getRawType().isAssignableFrom(Color.class)) {
throw new IllegalArgumentException("Cannot convert type " + toType.getType().getTypeName());
}
if (value == null || value.isBlank()) {
return null;
}
return Color.decode(value);
}
}
Then, a Matcher. I generalized.
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.AbstractMatcher;
// Omitted: other imports
public class SubclassMatcher extends AbstractMatcher<TypeLiteral<?>> {
private final Class<?> type;
public SubclassMatcher(Class<?> type) {
this.type = type;
}
#Override
public boolean matches(TypeLiteral<?> toType) {
return toType.getRawType().isAssignableFrom(type);
}
}
Finally, add the following line to the Guice module.
import com.google.inject.AbstractModule;
// Omitted: other imports
public class ExampleModule extends AbstractModule {
#Override
protected void configure() {
binder().convertToTypes(new SubclassMatcher(Color.class), new ColorTypeConverter());
// Omitted: other configurations
}
}
Now, the following injection works.
public class Example {
#Inject
#Named("com.example.background-color")
private Color backgroundColor;
}
It could be prettier. There exists a com.google.inject.matcher.Matchers API which I wasn't able use and could have solved my problem without constructing my personal SubclassMatcher class. See, Matchers.subclassesOf(Class<?>). It's for sure my fault as I don't believe Google wouldn't think of this pretty common use-case. If you find a way to make it work, please leave a comment.
Guice can't do that for you.
I suppose the conversion from String to int happens upon injection and not when you call Names.bindProperties(...)
See the bindProperties methods:
/** Creates a constant binding to {#code #Named(key)} for each entry in {#code properties}. */
public static void bindProperties(Binder binder, Map<String, String> properties) {
binder = binder.skipSources(Names.class);
for (Map.Entry<String, String> entry : properties.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
binder.bind(Key.get(String.class, new NamedImpl(key))).toInstance(value);
}
}
/**
* Creates a constant binding to {#code #Named(key)} for each property. This method binds all
* properties including those inherited from {#link Properties#defaults defaults}.
*/
public static void bindProperties(Binder binder, Properties properties) {
binder = binder.skipSources(Names.class);
// use enumeration to include the default properties
for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements(); ) {
String propertyName = (String) e.nextElement();
String value = properties.getProperty(propertyName);
binder.bind(Key.get(String.class, new NamedImpl(propertyName))).toInstance(value);
}
}
They are just binding strings.
You could just copy one of them and create your own binding. If the property value is in a color format, bind it additionally as Color.
As an example:
public class GuiceColors {
public static class GameModule extends AbstractModule {
#Override
protected void configure() {
Properties props = new Properties();
try {
props.load(getClass().getResourceAsStream("application.properties"));
} catch (IOException e) {
e.printStackTrace();
}
bindPropertiesWithColors(props);
}
private void bindPropertiesWithColors(Properties properties) {
Binder binder2 = binder().skipSources(Names.class);
// use enumeration to include the default properties
for (Enumeration<?> e = properties.propertyNames(); e.hasMoreElements();) {
String propertyName = (String) e.nextElement();
String value = properties.getProperty(propertyName);
try {
Color decodedColor = Color.decode(value);
binder2.bind(Key.get(Color.class, Names.named(propertyName)))
.toInstance(decodedColor);
} catch (NumberFormatException ex) {
// property value cannot be decoded as color, ignore the exception
}
binder2.bind(Key.get(String.class, Names.named(propertyName))).toInstance(value);
}
}
}
public static class Example {
#Inject
#Named("com.example.background-color")
private Color color;
#Inject
#Named("com.example.background-color")
private String colorString;
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new GameModule());
System.out.println(injector.getInstance(Example.class).color);
System.out.println(injector.getInstance(Example.class).colorString);
}
}
with application.properties being:
com.example.background-color = 0x333333

Java how to read a variable which is passed to args[0] from other public class methods

I am trying to read arguments passed to a jar file but my doubt is - If there is any way that we can read the constructor of parent class variables directly from subclass for example
KafkaSparkStreaming is my parent class and my hbaseconnection is my subclass now my doubt is how to get hostname from parent class passed as arguments to my child class Hbaseconnection also I don't want to set this as a parameter maybe whole understanding pass by reference and value might be wrong.
PARENT CLASS
public class KafkaSparkStreaming {
public String hostDetails;
public String zipCodePath;
public KafkaSparkStreaming(String[] args){
this.hostDetails = args[0];
this.zipCodePath = args[1];
}
public static void main(String[] args) throws Exception {
if(args.length<2) {
System.out.println("Arguments must be supplied ");
System.out.println("Usage: args[0] --> hostName args[1] --> path of zipcodecsv file");
System.exit(1);
}
KafkaSparkStreaming cdhHost = new KafkaSparkStreaming(args);
}
}
CHILD CLASS
public class HbaseConnection extends KafkaSparkStreaming implements
Serializable {
public static String host;
public HbaseConnection(String[] args) {
super(args);
}
private static final long serialVersionUID = 1L;
static Admin hbaseAdmin = null;
public static Admin getHbaseAdmin() throws IOException {
org.apache.hadoop.conf.Configuration conf =
(org.apache.hadoop.conf.Configuration) HBaseConfiguration.create();
conf.setInt("timeout", 12000000);
conf.set("hbase.master","cloudera-instance:60000");
conf.set("hbase.zookeeper.quorum", "cloudera-instance");
conf.set("hbase.zookeeper.property.clientPort", "2181");
conf.set("zookeeper.znode.parent", "/hbase");
Connection con = ConnectionFactory.createConnection(conf);
try {
if (hbaseAdmin == null)
//hbaseAdmin = new HBaseAdmin(conf);
hbaseAdmin = con.getAdmin();
} catch (Exception e) {
e.printStackTrace();
}
return hbaseAdmin;
}
Since hostDetails is a public property in KafkaSparkStreaming and HbaseConnection extends KafkaSparkStreaming objects of type HbaseConnection have access to that property from parent class. You can use it directly in HbaseConnection.
Since HbaseConnection is a sub-class of KafkaSparkStreaming, you can simply access it using its name as shown below -
public class HbaseConnection extends KafkaSparkStreaming {
// rest of your code
public void getDetails() {
// do something here
System.out.println("Host details from sub-class" + hostDetails);
}
}

How to save static variable when I serialize

My Goal: I need to keep the App state exactly in same sate after shutdown, lets say it's equivalent to "suspend" state.
My Problem : I do know that serialization mechanism doesn't save transient variables neither static variables. However I need to maintain the static variables in exactly same state after App suspension/shut down.
Approach-1 : I could save the state of static variable(s) into a different file, using my "file format", and serialize the objects into a different one.
a) Is this the "normal" approach?
Approach-2 : If I extend the ObjectInputStream/ObjectOutputStreamand override the methods readStreamHeader/writeStreamHeaderI can write whatever I want. So I can also write my static variables.
b) Am I doing something I should not?
Here's the code I've written testing approach-2, and seams to work fine. Please note, I'm not a Java programmer, so for it's very important to understand best practices, if there's any in this particular case.
#SuppressWarnings("serial")
class SequenceIdentifier implements Serializable
{
protected static long seqIdentifier_ = 1L; //This variable MUST NOT be reseted.
private long id_; //Object variable to be serialised.
private SequenceIdentifier(long id)
{ id_ = id;
}
#Override
public String toString()
{ return ("Id : " + id_ + " of " + seqIdentifier_);
}
public static SequenceIdentifier newInstance()
{ return new SequenceIdentifier(seqIdentifier_++);
}
}
final class OOStream extends ObjectOutputStream
{
public OOStream(OutputStream out) throws IOException
{ super(out);
}
#Override
protected void writeStreamHeader() throws IOException
{ super.writeLong(SequenceIdentifier.seqIdentifier_);
}
}
final class OIStream extends ObjectInputStream
{
public OIStream(InputStream in) throws IOException
{ super(in);
}
#Override
protected void readStreamHeader() throws IOException
{ SequenceIdentifier.seqIdentifier_ = super.readLong();
}
}
public class Main
{
public static void dump(ArrayList<SequenceIdentifier> ids)
{
for (SequenceIdentifier id : ids)
System.out.println(id);
}
public static void saveData()
{
ArrayList<SequenceIdentifier> ids = new ArrayList<>(Arrays.asList(SequenceIdentifier.newInstance(),
SequenceIdentifier.newInstance(),
SequenceIdentifier.newInstance(),
SequenceIdentifier.newInstance()));
try (OOStream oOut = new OOStream(new FileOutputStream("foo.bin")))
{ oOut.writeObject(ids);
} catch (Exception e)
{ System.err.println(e);
}
dump(ids);
}
#SuppressWarnings("unchecked")
public static void loadData()
{
ArrayList<SequenceIdentifier> ids = null;
try (OIStream oIn = new OIStream(new FileInputStream("foo.bin")))
{ ids = (ArrayList<SequenceIdentifier>)oIn.readObject();
} catch (Exception e)
{ System.err.println(e);
}
dump(ids);
}
public static void main(String[] args)
{
saveData();
System.out.println("Counter at this point " + SequenceIdentifier.seqIdentifier_);
SequenceIdentifier.seqIdentifier_ = 0;
loadData();
System.out.println("Counter at this point " + SequenceIdentifier.seqIdentifier_);
}
}
I would create a separate Memento-class containing all the relevant data as fields and de-/serialize that.
class MyClassWithStaticFields1 {
private static String field;
}
class MyClassWithStaticFields2 {
private static String field;
}
class StaticMemento {
String field1;
String field2;
}
// serialization
StaticMemento mem = new StaticMemento();
mem.field1 = MyClassWithStaticFields1.field;
mem.field2 = MyClassWithStaticFields2.field;
outputStream.writeObject(mem);
// deserialize
StaticMemento mem = outputStream.readObject();
MyClassWithStaticFields1.setField(mem.field1);
MyClassWithStaticFields2.setField(mem.field2);
So basically your Approach-1.
Several possibilities.
Make it non-static.
Write complementary readObect()/writeObject() methods that call defaultReadObject() and defaultWriteObject() respectively and then serialize/deserialize the field.
Write complementary writeReplace()/readResolve() methods that substitute a proxy object that does contain this member as a non-transient non-static member.
Make the object Externalizable and take complete control of the serialization process yourself in the associated methods.
Review your requirement.

java Object null after instance and calling inside method

can anyone help me with this issue, i'm working with java using SQLMap(ibatis).
i have 3 class which is MainConfiguration, SQLMap, DBUtility.
Main Configuration (this class is using to set an object inside SQLMap class)
public class MainConfiguration
{
public static String file = "configuration/db/SQLMapConfig.conf";
public static void main(String[] args) throws Exception
{
new MainConfiguration().loadConfiguration();
}
public static void loadConfiguration()
{
SQLMap.setMapFile(file);
List list = DBUtility.loadUsers();
}
}
SQL Map (this class is the getter and setter of and object)
public final class SQLMap
{
private static SqlMapClient sqlMap;
public static void setMapFile(String sMapFile)
{
try
{
sqlMap = SqlMapClientBuilder.buildSqlMapClient(new FileReader(sMapFile));
}
catch (Exception e)
{
throw new RuntimeException("Error initializing SqlMapClient class", e);
}
}
public static SqlMapClient getSqlMapInstance()
{
return sqlMap;
}
}
DBUtility (this class is where object instance and get object from SQLMap class)
public class DBUtility
{
// object utility
protected static SqlMapClient sqlMap = SQLMap.getSqlMapInstance();
//constructor
public DBUtility() throws Exception
{
}
public static List loadUsers()
{
//it's working
logger.info("SQLMap Get Instance = " + SQLMap.getSqlMapInstance());
//it's not working
logger.info("SQLMap Get Instance = " + sqlMap);
//code below will be error because of null sqlMap
try
{
listUser = sqlMap.queryForList("getUsers");
}
catch (Exception sqle)
{
logger.error("Error on load all user", sqle);
}
return listUser;
}
}
the logger give me this :
SQLMap Get Instance = com.ibatis.sqlmap.engine.impl.SqlMapClientImpl#76707e36
SQLMap Get Instance = null
how come the second log give me null, even i have instance the object?
Your field sqlMap is initialized when the DBUtility class is loaded, which apparently happens before SQLMap.setMapFile(file); is called. So, sqlMap points at different things: null in the static field, and an actual instance when you call the getter in loadUsers().
The problem is that DBUtility looks up the sqlMap too early. It has to wait until the file is passed to SQLMap. Change your code like this to delay the initialization of DbUtility.sqlMap:
public static void loadConfiguration()
{
SQLMap.setMapFile(file);
DBUtility.initMapClient(); // notify DBUtility
List list = DBUtility.loadUsers();
}
public class DBUtility
{
protected static SqlMapClient sqlMap; // do not initialize too early
public static void initMapClient()
{
sqlMap = SQLMap.getSqlMapInstance(); // wait for SQLMap to be ready
}
Of course, it would be simpler if you did not even have the sqlMap field in DBUtility. Just call SQLMap.getSqlMapInstance() every time you need it. This is especially important in case the instance ever changes:
listUser = SQLMap.getSqlMapInstance().queryForList("getUsers");
Read When are static variables are initialized? for a more detailed explanation of static fields.

Xpages: How to ensure my cacheBean only loads once

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.

Categories

Resources