java Object null after instance and calling inside method - java

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.

Related

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.

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.

Call a static method from abstract class

I have a class like this
parent class DevPortalTestController is absract
public class SeleniumWebDriverFactory extends DevPortalTestController {
public static RemoteWebDriver mDriver;
public SeleniumWebDriverFactory(RemoteWebDriver whichDriver)throws UnsupportedOSException, PoisonException {
super(whichDriver);
mDriver = whichDriver;
}
public List<TestContext> getBrowserTestContext(List<String> browsers)
throws Exception {
PhoenixDriver driver = null;
List<TestContext> contexts = new ArrayList<TestContext>();
logger.info("Setting browser context...");
Login login = retrieveLoginData();
for (String browser : browsers) {
// operations
Map<String, Object> browserMap = new HashMap<String, Object>();
// Populate the map with DevPortalTestController objects.
browserMap.put(MasterConstants.BROWSER, this);
.....
.....
}
return contexts;
}
public static List<TestContext> getTestContext(List<String> browsers)
throws Exception {
SeleniumWebDriverFactory instanceSel = new SeleniumWebDriverFactory(mDriver);
List<TestContext> contexts = instanceSel.getBrowserTestContext(browsers);
return contexts;
}
}
I need to call this getTestContext method in another class
for that am doing like this.Also that class is extenting another parnet class
public class DevPortalTest extends Test {
RemoteWebDriver rmDriver ;
SeleniumWebDriverFactory selFac =new SeleniumWebDriverFactory(rmDriver);
#Override
public List<TestContext> getTestContexts() {
try {
String os = System.getProperty("os.name");
if (SystemDetail.deviceIsRunningWindows()) {
return selFac.getTestContext(ZucchiniConstants.allBrowsers);
else {
throw new TestException(os + " is not supported");
}
} catch (Exception e) {
logger.error("", e);
}
return null;
}
}
But in this place
SeleniumWebDriverFactory selFac =new SeleniumWebDriverFactory(rmDriver);
I'm getting
Default constructor cannot handle exception type PoisonException
thrown by implicit super constructor. Must define an explicit
constructor
How can i call the method getTestContext inside DevPortalTest test class?
The problem is that initializer code will be placed in the "default constructor" which cannot throw any exception. Define an empty constructor that throws the exceptions to proceed.
e.g.,
DevPortalTest() throws UnsupportedOSException, PoisonException { }
You have to add the constructor to your test code:
public DevPortalTest() throws UnsupportedOSException, PoisonException {
SeleniumWebDriverFactory selFac = new SeleniumWebDriverFactory(rmDriver);
}
also, i assume you're injecting RemoteWebDriver rmDriver;
Since the method is static, you don't need an object to call it.
SeleniumWebDriverFactory.getTestContext(ZucchiniConstants.allBrowsers);
As an alternative to creating a constructor you can also do this
public class DevPortalTest extends Test {
RemoteWebDriver rmDriver ;
SeleniumWebDriverFactory selFac;
// this code block runs before constructor
{
try{
selFac = new SeleniumWebDriverFactory(rmDriver);
}catch(Exception e){
// handle exception
}
}
Static method can be accessed using class Name so there is no need to create any Object in Abstract class.

Java - Access to non-static properties with reflection

I want to get my class property with string name.
I have a code like this
class Test
{
public String simple = "hello";
public void getSetting()
{
try
{
Test c = new Test();
Class cls = this.getClass();
Field field = cls.getField("simple");;
}
catch(Exception e)
{
// error
}
}
}
I get an error with this code , because my property is non-static , and when i changing my property to static , it's work fine , how can i get non-static properties with reflection?
Here's a self-contained example on how to get an instance Field through reflection.
public class Main {
// the instance field
String simple = "foo";
// some static main method
public static void main(String[] args) throws Exception {
// initializing the class as we're accessing an instance method
new Main().reflect();
}
public void reflect() {
Class<?> c = this.getClass();
try {
// using getDeclaredField for package-protected / private fields
Field field = c.getDeclaredField("simple");
// printing out field's value for this instance
System.out.println(field.get(this));
}
// TODO handle better
catch (IllegalAccessException iae) {
iae.printStackTrace();
}
catch (NoSuchFieldException n) {
n.printStackTrace();
}
}
}
Output
foo
try
{
Test c = new Test();
Class cls = c.getClass(); //Change this.getClass to c.getClass()
Field field = cls.getField("simple");;
}
The Field must be static or belong to a instance that can be get via reflection.

Getting Java beans that were set in a try method

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();

Categories

Resources