My j2me application call destroyApp() and notifyDestroyed() when it wants to be closed
when I run it on blackberry, in the second launch the static variables will have the same values they had in previous run.
Why they don't get the initial value? How can I make sure the application initialize static variables?
This discussion at Blackberry support forums suggests that it is a known issue with BlackBerry MIDlets - at least with those using static push registries. Workarounds they suggest are either re-define static variables in startApp or get rid of static push.
This post looks worth extensive quoting, since there is a nice code example and issue analysis:
The simplest example I could come up with is this:
public class BasicMIDlet extends MIDlet {
private static byte myByte = Byte.MIN_VALUE;
public void startApp() {
System.out.println("My byte: " + myByte);
myByte = Byte.MAX_VALUE;
notifyDestroyed();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
You would expect myByte to output to -128 every time the app starts,
but this is my output:
--------------------------------------------------------
Starting BBTest
Started BBTest(159)
Foreground BBTest(157)
My byte: -128 <------------
Foreground net_rim_bb_ribbon_app(83)
Exit BBTest(159)
Starting BBTest
Started BBTest(160)
Foreground BBTest(157)
My byte: 127 <------------
Foreground net_rim_bb_ribbon_app(83)
Exit BBTest(160)
Starting BBTest
Started BBTest(161)
Foreground BBTest(157)
My byte: 127 <------------
Foreground net_rim_bb_ribbon_app(83)
Exit BBTest(161)
--------------------------------------------------------
I have noticed something, if I remove the static push registries, the
application behaves normally and outputs -128 every time. An yes, I
have the same feeling that a MIDlet runs on top of a RIMlet, and in
the case the midlet defines push registries, the RIMlet is running all
the time. So my question now is, are there any solutions other than
initializing the static variables on every run (because there are
roughly >1000 such members in my app)
Yep, blackberry midlets retain the values of static variables. This is an issue, and the only way I see to fix it is that in the startup we need to assign null values to the static values. For example if a static var is declared like:
public static String State = null;
And in the life cycle of the middle the value is set to "closed";
Then in the next startup of the application, the value remains "closed" instead of null.
I guess you mean "in the second launch the static variables will not have the same values they had in previous run".
Static variables can only maintain their value through the lifetime of the app. The app ends when destroyApp()/notifyDestroyed() is called, so the values are lost!
To persist state over multiple runs, use the RecordStore.
Related
Any Android App produces Logs in the LogCat, even those not generated by developer's source code via Log.d, Log.i, Log.w and Log.e etc. etc. etc.. Perhaps Google Developers has some "automagic" thing for this, I don't know about that...
The point is I remember, years ago, I could somehow extend the class Application, override one or several of it's methods, and then:
Add my own code to process any single Log object generated by my
App in the LogCat
Do whatever I wanted with them (getting the label and the description strings, and then send them via mail, Slack etc., basically)
And then, calling super on that method and let the system do with that Log whatever Application by default does with it...
or something like that... if I recall correctly, I could do this with any log in my app's namespace. Or maybe it was just the crash handler? I can't remember...
It's been so long since I accomplished that (several years already!), so I don't remember how could I do that anymore... I search the internet like crazy trying to recall, but I am struggling to find it again... :-S
// ...public?? oO
[¿¿??] class MyApp extends Application [...] {
// [...]
#Override
public void whateverMethodItWasIDontRemember(params) {
// My coding stuff for the error reports
/* magic :D */
sendTheLogsMyWay();
// I bet this is important
super.whateverMethodItWasIDontRemember(params);
}
// [...]
}
I am about to launch the first Beta version of a new app, so I want beta testers to have a reliable way to send me LogCat's feed if anything has to be reported due to crashes, unexpected behaviour etc.
I mean, it would be ridiculous having to fill with CustomLogs every inch of source code for the beta version, when, in most cases, default logs are more than enough to see why it crashed (errors), or what optimization problems (usually warnings) might the Beta Tester have... not to mention that, if I forget to monitor something this way, the ridiculously big effort to log every single line of my code would be useless... oO
// -__- Mmm... perhaps extending Log itself
// would be more elegant...
import android.util.Log
public final class CustomLog {
public static void d(String label, String msg) {
// AKA My code to handle it
packItForNextErrorReport(label, msg);
Log.d(label, msg);
}
/*
* ... and so on with Log.i, w and e.
* ...I think you get the idea
*/
}
does anyone know how to replace variable value after a program that changes it? I tried static variable before, but it doesn't save after you close the program.
For example
import java.lang.Math;
public class Main {
static int A1;
public static void main (String [] args) {
A1=(int) (1+Math.random()*10);
}
}
Let's say the first time the program is run, A1 holds a value of 5. Is it possible that next time the program is run, A1 still holds a value of 5 instead of zero? (before reaching the main method)
Thanks
Of course not, when the program exits the portion of memory it was using is freed for other programs. The only way to do it is writing to a file and restore the value from the file at the initialization of the program.
The most easy to do that in Java is to use Preferences API, the most easy way to use it is
prefs = Preferences.userRoot().node(this.getClass().getName());
String ID = "A1";
if (prefs.getInt(ID, -1)
prefs.putInt(ID, (int) (1+Math.random()*10));
A1 = prefs.getInt(ID, -1)
to get more info, juste Google "java preferences api"
I am having some strange trouble with the method await(Future future) of the Controller.
Whenever I add an await line anywhere in my code, some GenericModels which have nothing to do with where I placed await, start loading incorrectly and I can not access to any of their attributes.
The wierdest thing is that if I change something in another completely different java file anywhere in the project, play will try to recompile I guess and in that moment it starts working perfectly, until I clean tmp again.
When you use await in a controller it does bytecode enhancement to break a single method into two threads. This is pretty cool, but definitely one of the 'black magic' tricks of Play1. But, this is one place where Play often acts weird and requires a restart (or as you found, some code changing) - the other place it can act strange is when you change a Model class.
http://www.playframework.com/documentation/1.2.5/asynchronous#SuspendingHTTPrequests
To make it easier to deal with asynchronous code we have introduced
continuations. Continuations allow your code to be suspended and
resumed transparently. So you write your code in a very imperative
way, as:
public static void computeSomething() {
Promise delayedResult = veryLongComputation(…);
String result = await(delayedResult);
render(result); }
In fact here, your code will be executed in 2 steps, in 2 different hreads. But as you see it, it’s very
transparent for your application code.
Using await(…) and continuations, you could write a loop:
public static void loopWithoutBlocking() {
for(int i=0; i<=10; i++) {
Logger.info(i);
await("1s");
}
renderText("Loop finished"); }
And using only 1 thread (which is the default in development mode) to process requests, Play is able to
run concurrently these loops for several requests at the same time.
To respond to your comment:
public static void generatePDF(Long reportId) {
Promise<InputStream> pdf = new ReportAsPDFJob(report).now();
InputStream pdfStream = await(pdf);
renderBinary(pdfStream);
and ReportAsPDFJob is simply a play Job class with doJobWithResult overridden - so it returns the object. See http://www.playframework.com/documentation/1.2.5/jobs for more on jobs.
Calling job.now() returns a future/promise, which you can use like this: await(job.now())
I've tried to solve this issue by referring possible duplicates but none of them seem to be helpful.
Here's a code that I'm using to call Win API methods in Java to get current Windows User Name, and a native Windows MessageBox, but I'm getting UnsatisfiedLinkError that says that my code is unable to locate the native method I'm trying to call.
public class TestNative
{
public static void main(String[] args)
{
long[] buffer= { 128 };
StringBuffer username = new StringBuffer((int)buffer[0]);
GetUserNameA(username,buffer);
System.out.println("Current User : "+username);
MessageBoxA(0,"UserName : "+username,"Box from Java",0);
}
/** #dll.import("ADVAPI32") */
static native void GetUserNameA(StringBuffer username,long[] buffer);
/** #dll.import("USER32") */
private static native int MessageBoxA(int h,String txt,String title,int style);
}
What can be my possible (relatively simple) solution to call native Windows methods in Java. I realize that it will kill the very reason of Java being a cross-platform language, but I need to work on a project for Windows, to be developed in Java.
Thanks.
Update
As David Heffernan suggested, I've tried changing the method signature of MessageBox to MessageBoxA, but still it's not working.
I would guess it's related to the signatures not matching completely.
The GetUserName function takes two parameters: a LPTSTR and a LPDWORD. Java will likely not handle the StringBuffer acting as a TCHAR array for you.
Also, why bother using the Windows API for this? Java can probably get the user's logon name (quick google says: System.getProperty("user.name")), and Swing can make a message box (even one that looks like a Windows one).
Have you tried https://github.com/twall/jna. I have heard good things and its supposed to make jni that bit easier with many conveniences and simplifications.
Do you have a -Djava.library.path VM arg set with the path to your DLL's? Alternatively, you can have it in your system PATH.
The error is because there is no MessageBox. You presumably mean MessageBoxA.
We're using Spring/Hibernate on a Websphere Application Server for AIX. On my Windows machine, the problem doesn't occur--only when running off AIX. When a user logs in with an account number, if they prefix the '0' to their login ID, the application rejects the login. In the DB2 table, the column is of numeric type, and there shouldn't be a problem converting '090....' to '90...'
Anyone else experience a problem like this? Both machines have Java v1.5.
To be more specific, the flow is FormView -> LoginValidator -> LoginController
In LoginValidator, the value of login is null with the prefixed 0. Without the 0, the value is what it should be (But again, this is only on the AIX environment--on 2 Windows environments it's fine). Here's the snippet of code where the object equals null..
public class LoginValidator implements Validator {
public boolean supports(Class clazz) {
return Login.class.equals(clazz);
}
#SuppressWarnings("all")
public void validate(Object obj, Errors errors) {
System.out.println("Inside LoginValidator");
Login login = (Login) obj;
//null value
System.out.println("Before conversion in Validator, store id = "
+ login.getStoreId());
}
}
I've also written this short Java program for constructing a Long from a String, and using the java binary that is packaged with WebSphere
public class String2Long {
public static void main(String[] args){
String a = "09012179";
String b = "9012179";
Long _a = new Long(a);
Long _b = new Long(b);
System.out.println(a + " => " + _a); //09012179 => 9012179
System.out.println(b + " => " + _b); //9012179 => 9012179
System.out.println("_a.equals(_b) " + _a.equals(_b)); //_a.equals(_b) true
}
}
SOLUTION
Well there's an awful lot of things going on there. You really need to try to isolate the problem - work out what's being sent to the database, what's being seen by Java etc.
Try to pin it down in a short but complete program which just shows the problem - then you'll be in a much stronger position to file a bug or fix your code.
SOLUTION
A co-worker did some research on Spring updates, and apparently this error was correct in v. 2.5.3:
CustomNumberEditor treats number with leading zeros as decimal (removed unwanted octal support while preserving hex)
We were using Spring 2.0.5. We simply replaced the jars with Spring 2.5.4, and it worked as it should have!
Thanks to everyone for your help/assistance. We will make use of Unit tests in the future, but this just turned out to be a Spring bug.
Trace through the program following the path of the String all the way to database and make unit tests for every single method on that path. And don't just take the shortest possible route here, make multiple unit tests with different inputs and expected outputs to really see what went possibly wrong. Assuming you don't find any errors, run the same unit tests on the other computer and you should be able to pinpoint the bug. From the top of my head I'd assume it may have something to do with case sensitivity but there really is no way to be sure.
Next time, use TDD.
I don't know much about Java, but this might happen the string is interpreted as octal string because of the leading "0".
You can probably work around this using Long.parseLong(a, 10).