nullPointerException in a MIDLet - java

I have written the following Java Application:
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.MIDlet;
public class JavaApplication6 extends MIDlet
{
private static Form clockForm=null;
private static StringItem clockItem=new StringItem("hello", "World!");
private static ClockTask task=null;
private static Timer timer=null;
static class ClockTask extends TimerTask
{
private int count=0;
#Override
public void run()
{
count++;
clockItem.setText("hello "+count);
}
}
public static void JavaApplication6() throws Exception
{
clockForm=new Form("Clock");
clockItem=new StringItem("","0");
clockForm.append(clockItem);
}
#Override
public void startApp()
{
task=new ClockTask();
timer=new Timer();
timer.schedule(task,1000,1000);
Display.getDisplay(this).setCurrent(clockForm);}
#Override
public void pauseApp()
{}
public void destroyApp(boolean unconditional)
{}
public static void main(String[] args) {
JavaApplication6 test=new JavaApplication6();
test.startApp();
}
}
but when I run it, it gives me the following exception on the last line of startApp();
Exception in thread "main" java.lang.NullPointerException
at javax.microedition.lcdui.Display.<init>(Display.java:420)
at javax.microedition.lcdui.Display.getDisplay(Display.java:447)
at javaapplication6.JavaApplication6.startApp(JavaApplication6.java:42)
at javaapplication6.JavaApplication6.main(JavaApplication6.java:56)

You created static method JavaApplication6 named as it is the constructor. But it is not. So it is not called when you say JavaApplication6 test=new JavaApplication6();. Therefore clockForm remains uninitialized, i.e. null. So, line
Display.getDisplay(this).setCurrent(clockForm);
throws NPE becuase clockForm is null at this point.
The solution is to remove static void from line public static void JavaApplication6() throws Exception. It should look like
public JavaApplication6() throws Exception
In this case it becomes constructor and everything will work.
Good luck.

You seem to be approaching things in a fundamentally wrong way.
I mean, even if you somehow manage to figure and hack through all of the null pointer exceptions, you will not get a valid MIDlet application code.
Thing is, because class JavaApplication6 extends MIDlet, the following line will throw runtime exception at any properly functioning MIDP implementation (read: at any correctly working device):
JavaApplication6 test=new JavaApplication6(); // SecurityException in runtime
This is the way how things are specified by MIDP (JSR 118) API. Above line means that application attempts to invoke MIDlet constructor bypassing the AMS, which will cause SecurityException in runtime.
This is clearly explained in MIDlet constructor javadocs, note what is stated in Throws:
protected MIDlet()
Protected constructor for subclasses. The application management software
is responsible for creating MIDlets and creation of MIDlets is restricted.
MIDlets should not attempt to create other MIDlets.
Throws:
SecurityException - unless the application management software is creating
the MIDlet.

Related

How to properly use a "lock" variable for synchronization in a Serializable class?

I am trying to figure out how to avoid an NPE in the the code below. I am unable to purposely reproduce the error, but every once in a while I get an NPE at the line 40 synchronized(lock) {. My guess is that it's happening after a serialization/deserialization process - but that is just a guess.
My IDE gives me a compile "tip" that says synchronization on a non-final variable (lock), but to be quite honest, I'm not as familiar with synchronized code blocks and how a serializable class affects final variables.
As an FYI, the code below was copied/modified from a Struts Wiki: https://cwiki.apache.org/confluence/display/WW/HibernateAndSpringEnabledExecuteAndWaitInterceptor (towards the bottom of the page in the comments).
import com.opensymphony.xwork2.ActionInvocation;
import org.apache.struts2.interceptor.BackgroundProcess;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class OpenSessionBackgroundProcess extends BackgroundProcess implements Serializable {
private static final long serialVersionUID = 3884464561311686443L;
private final transient EntityManagerFactory entityManagerFactory;
// used for synchronization
protected boolean initializationComplete;
private transient Object lock = new Object();
public OpenSessionBackgroundProcess(String name, ActionInvocation invocation, int threadPriority, EntityManagerFactory entityManagerFactory) {
super(name, invocation, threadPriority);
this.entityManagerFactory = entityManagerFactory;
initializationComplete = true;
synchronized (lock) {
lock.notify();
}
}
protected void beforeInvocation() throws Exception {
while (!initializationComplete) {
try {
synchronized (lock) { // <----- NPE HERE
lock.wait(100);
}
} catch (InterruptedException e) {
// behavior ignores cause of re-awakening.
}
}
EntityManager em = entityManagerFactory.createEntityManager();
TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(em));
super.beforeInvocation();
}
protected void afterInvocation() throws Exception {
super.afterInvocation();
EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.unbindResource(entityManagerFactory);
EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
}
/**
* Override default readObject() method when deserializing
*
* #param serialized the serialized object
*/
private void readObject(ObjectInputStream serialized) throws IOException, ClassNotFoundException {
serialized.defaultReadObject();
lock = new Object();
}
}
The code in the question and the linked wiki page has an unresolvable data race condition. Unfortunately, the constructor of BackgroundProcess allows a reference to this to escape the constructor by starting a new thread that calls beforeInvocation. Because this call can occur before the constructor of the child class completes, it is not safe to extend BackgroundProcess.
This code attempts to handle the race condition on entityManagerFactory through use of the lock object, initializationComplete flag, and wait/notify usage. However, this only moves the race condition from entityManagerFactory to lock, as Java only initialises the fields of subclasses after the parent class constructor completes. This is true regardless of whether the field is initialised inline or in the constructor.
You can find more details about this problem in the excellent accepted answer to the question Java: reference escape.
My best advice is to avoid the use of BackgroundProcess and find another way to solve the original problem.

aspectj cross-thread pointcut

I am new with AspectJ annotation for Java, and I am wondering if it is possible to put pointcut on a cross thread invocation.
Here is the code:
public class App {
public static void main( String[] args ) {
new Connector().getStart("testtest");
}
}
public class Connector {
public void getStart(String s1) {
Handler h = new Handler(s1);
h.start();
}
}
public class Handler extends Thread {
String s1;
public Handler(String s1) {
this.s1 = s1;
}
public void run() {
new Plain().getValue(s1);
}
}
public class Plain {
public void getValue(String s1) {
System.out.println("Plain getValue: " + s1);
}
}
I would like to have a pointcut that only triggers when Plain.getValue() is called by Connector.getStart().
Is it possible? Thanks.
You are making a mistake believing that Plain.getValue(..) is called by Connector.getStart(..) because in a multi-threaded environment it is not. Let me prove it with a little tweak to the getValue(..) method, printing a stack trace:
package de.scrum_master.app;
public class Plain {
public void getValue(String s1) {
System.out.println("Plain getValue: " + s1);
new Exception().printStackTrace(System.out);
}
}
By the way, I have moved all your classes to package de.scrum_master.app because using the default package is discouraged in Java and also AspectJ does not like it when trying to match pointcuts.
Console log (multi-threaded):
Plain getValue: testtest
java.lang.Exception
at de.scrum_master.app.Plain.getValue(Plain.java:4)
at de.scrum_master.app.Handler.run(Handler.java:9)
See? There is no trace of Connector.getStart(..) in the log. If we also tweak getStart(..) so as to call the thread's run() method directly (i.e. not starting a new thread but executing in the same thread) instead of start(), the situation changes:
package de.scrum_master.app;
public class Connector {
public void getStart(String s1) {
Handler h = new Handler(s1);
h.run();
}
}
Console log (single-threaded):
Plain getValue: testtest
java.lang.Exception
at de.scrum_master.app.Plain.getValue(Plain.java:4)
at de.scrum_master.app.Handler.run(Handler.java:9)
at de.scrum_master.app.Connector.getStart(Connector.java:4)
at de.scrum_master.app.App.main(App.java:3)
In this situation we could use AspectJ's dynamic cflow() (control flow) pointcut like this:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class SingleThreadAspect {
#Before("execution(* de.scrum_master.app.Plain.getValue(..)) && cflow(execution(* de.scrum_master.app.Connector.getStart(..)))")
public void interceptControlFlow(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
The advice would be triggered just as you wish. But for the reason explained at the beginning of my answer cflow() does not (and cannot) work across threads because there is no such thing as a direct control flow across threads. Each thread's control flow starts with its run() method, no earlier. That is the whole concept of multi-threading.
So if you really want to emulate something like a cross-thread control flow for whatever doubtful reason, you need to do some manual bookkeeping.
But first let us revert the tweaked h.run() back to the original h.start() so as to reinstate the multi-threading situation. Let us also remove the printStackTrace(..) line from Plain.getStart(..).
Solution:
Disclaimer: I do not like annotation-style #AspectJ syntax, so I am switching over to native syntax. It is much more expressive and we can achieve what we want more easily in terms of ITD (inter-type definition) because
in native syntax we can just declare an additional instance member variable for a given class while
in #AspectJ syntax we would have to declare the target class to implement an interface with a default implementation which in turn would carry the member variable for our manual bookkeeping.
Let us modify App so as to also start a Handler thread directly. This is our negative test case because we do not want to trigger our advice there as the thread is started outside of Plain.getValue(..):
package de.scrum_master.app;
public class App {
public static void main(String[] args) throws InterruptedException {
// The aspect should ignore this thread
new Handler("foo").start();
// Wait a little while so as not to mess up log output
Thread.sleep(250);
new Connector().getStart("testtest");
}
}
Console log without aspect:
Plain getValue: foo
Plain getValue: testtest
Aspect:
package de.scrum_master.aspect;
import de.scrum_master.app.*;
public aspect CrossThreadAspect {
// Declare a new instance member for our bookkeeping
private boolean Handler.cflowConnectorGetStart = false;
// If handler thread is started from Connector.getStart(..), set a mark
before(Handler handler) :
call(void Handler.start()) &&
cflow(execution(* Connector.getStart(..))) &&
target(handler)
{
System.out.println(thisJoinPoint + "\n doing bookkeeping");
handler.cflowConnectorGetStart = true;
}
// If current thread is a marked Handler, log it
before() :
execution(* Plain.getValue(..)) &&
if(Thread.currentThread() instanceof Handler) &&
if(((Handler) Thread.currentThread()).cflowConnectorGetStart)
{
System.out.println(thisJoinPoint + "\n triggered from parent thread via Connector.getStart(..)");
}
}
Console log with aspect:
As you can see, the Handler thread started from App.main(..) is ignored by the aspect as expected. The Handler started from Connector.getStart(..) triggers the aspect.
Plain getValue: foo
call(void de.scrum_master.app.Handler.start())
doing bookkeeping
execution(void de.scrum_master.app.Plain.getValue(String))
triggered from parent thread via Connector.getStart(..)
Plain getValue: testtest

JavaFX software design

In a JavaFX application, javafx.application.Application must be subclassed, and the inherited launch() method, although it's public, must be called from within this derived class, otherwise an exception is thrown. The launch() method then uses reflection to instantiate the derived class, making it difficult to set values for the class members without losing them when launching. All that appears totally unusual to me, and I was wondering why starting a JavaFX application is so complicated, if that kind of software design (design pattern?) has a name, or if it's just bad design?
EDIT:
To be more specific, I want to use the observer pattern, so my java application gets notified when a document was loaded, like this:
public class MyDocumentLoader extends Application
{
private ChangeListener<Worker.State> changeListener;
public void setChangeListener(ChangeListener<Worker.State> changeListener)
{
this.changeListener = changeListener;
}
...
public void loadDocument(String url)
{
webEngine.getLoadWorker().stateProperty().addListener(changeListener);
webEngine.load(url);
}
...
}
I need the callback member in several methods, and ideally I can have more than one instances of the class that loads documents, so I can set different ChangeListeners for different URLs.
My guess is that this design was motivated by the (vast) number of Swing applications that were incorrectly written, with the "primary" JFrames being instantiated and shown on the wrong thread (i.e. not on the AWT event dispatch thread). My guess is that so many Swing applications were incorrectly written that they had to defensively code the framework against the incorrect usage, and that they wanted to avoid this scenario with JavaFX.
Forcing (well, almost forcing, there are hack-arounds) an FX Application to start this way makes it much harder to write an application incorrectly in a similar way. The launch method (and the equivalent Oracle JVM startup process if you have an Application subclass without a main method and a call to launch) does quite a bit of boilerplate work: it starts the FX toolkit, instantiates the Application subclass and calls its init() method, then on the FX Application Thread it instantiates the primary Stage and passes it to the Application subclass's start(...) method. This then ensures everything is running on the correct thread.
You should basically consider the start(...) method in a JavaFX application as the replacement for the main(...) method in a "traditional" Java application, with the understanding it is invoked on the FX Application Thread.
My recommendation is that the Application subclass should be as minimal as possible; it should just delegate to something else to actually create the UI, and then should just place it in the primary stage and show it. Include a main method that does nothing other than call launch(...) as a fallback for non-JavaFX-aware JVMs. You should only have one instance of one Application subclass present in any JVM. This way your Application subclass has no class members to set, and so the issues you describe simply don't arise.
If you use FXML, this is actually fairly natural: the start(...) method essentially just delegates to the FXML-controller pair to do the real work. If you don't use FXML, create a separate class to do the actual layout, etc, and delegate to it. See this related question which gets at the same kind of idea.
Note also that your statement
the inherited launch() method, although it's public, must be called
from within this derived class
is not entirely accurate, as there is an overloaded form of the launch(...) method in which you can specify the application subclass. So, if you really need, you can just create a stub for starting the FX toolkit:
public class FXStarter extends Application {
#Override
public void start(Stage primaryStage) {
// no-op
}
}
Now you can do:
public class MyRegularApplication {
public static void main(String[] args) {
// start FX toolkit:
new Thread(() -> Application.launch(FXStarter.class)).start();
// other stuff here...
}
}
Note that launch does not return until the FX toolkit shuts down, so it is imperative to put this call in another thread. This potentially creates race conditions, where you may try to do something needing the FX toolkit before launch(...) has actually initialized it, so you should probably guard against that:
public class FXStarter extends Application {
private static final CountDownLatch latch = new CountDownLatch(1);
public static void awaitFXToolkit() throws InterruptedException {
latch.await();
}
#Override
public void init() {
latch.countDown();
}
#Override
public void start(Stage primaryStage) {
// no-op
}
}
and then
public class MyRegularApplication {
public static void main(String[] args) throws InterruptedException {
// start FX toolkit:
new Thread(() -> Application.launch(FXStarter.class)).start();
FXStarter.awaitFXToolkit();
// other stuff here...
}
}
SSCCE (I just used inner classes for everything so this is convenient to run, but in real life these would be standalone classes):
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class BackgroundProcessDrivenApp {
public static void main(String[] args) throws InterruptedException {
Platform.setImplicitExit(false);
new Thread(() -> Application.launch(FXStarter.class)).start();
FXStarter.awaitFXToolkit();
new MockProcessor().doStuff() ;
}
public static class FXStarter extends Application {
private static final CountDownLatch latch = new CountDownLatch(1);
#Override
public void init() {
latch.countDown();
}
public static void awaitFXToolkit() throws InterruptedException {
latch.await();
}
#Override
public void start(Stage primaryStage) { }
}
public static class MockProcessor {
private final int numEvents = 10 ;
public void doStuff() {
Random rng = new Random();
try {
for (int event = 1 ; event <= numEvents; event++) {
// just sleep to mimic waiting for background service...
Thread.sleep(rng.nextInt(5000) + 5000);
String message = "Event " + event + " occurred" ;
Platform.runLater(() -> new Messager(message).showMessageInNewWindow());
}
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
} finally {
Platform.setImplicitExit(true);
}
}
}
public static class Messager {
private final String message ;
public Messager(String message) {
this.message = message ;
}
public void showMessageInNewWindow() {
Stage stage = new Stage();
Label label = new Label(message);
Button button = new Button("OK");
button.setOnAction(e -> stage.hide());
VBox root = new VBox(10, label, button);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 350, 120);
stage.setScene(scene);
stage.setAlwaysOnTop(true);
stage.show();
}
}
}
JavaFX supports a great number of deployment and packaging strategies, ref. https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/toc.html, and having a standardized lifecycle entry- and exit-point simplifies supporting all these strategies.
If you are struggling to initialize your main application class, due to it being instanciated by the JavaFX launcher, your best option is to use the Application.init() and Application.stop() methods, as James_D points out.

How do you get event notifications back to the main program class of a Java console app?

I'm coming to Java from C#, and I'm really just trying to figure out how to do things in Java world. I'm running Java 8 in IntelliJ IDEA. I found this explaining events in Java as basically being hand-made through manual registration and an interface method call. The code example has enough problems that I assume it was never compiled. After cleaning that up a bit I have this:
Interface MetronomeEvent:
public interface MetronomeEvent {
void Tick(Date tickDate);
}
Class EventFiringSource:
public class EventFiringSource {
// Our collection of classes that are subscribed as listeners of our
protected List<MetronomeEvent> _listeners=new ArrayList();
// Method for listener classes to register themselves
public void addMetronomeEventListener(MetronomeEvent listener)
{
_listeners.add(listener);
}
// "fires" the event
protected void fireMetronomeEvent()
{
if (_listeners != null && !_listeners.isEmpty())
{
for (MetronomeEvent e:_listeners)
{
e.Tick(new Date());
}
}
}
public void Start()
{
fireMetronomeEvent();
}
}
Main console application:
public class MainApp implements MetronomeEvent {
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
source.addMetronomeEventListener(this); // Adds itself as a listener for the event
source.Start();
}
public void Tick(Date tickDate)
{
System.out.println(tickDate.toString());
}
}
The one remaining error is source.addMetronomeEventListener(this); where the compiler complains that it cannot reference MyApp.this from a static context. That makes sense, but I don't see any way then that I could, after implementing the MetronomeEvent interface on the main program class, actually pass it to source.addMetronomeEventListener() for registration. Is it impossible to directly register the main program class for events? Am I supposed to create and register a Listener class that implements MetronomeEvent and will act on behalf of the main application? Like this?
public class Listener implements MetronomeEvent {
public void Tick(Date tickDate){
System.out.println(tickDate.toString());
}
}
And then:
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
Listener l=new Listener();
source.addMetronomeEventListener(l); // Adds another object to listen on behalf of main()
source.Start();
}
This is not about events, it's about main() and static methods in general.
I would suggest writing your main() as
public static void main(String[] args) {
new MainApp(args).execute();
}
This way you're immediately jumping from static function world into object-oriented world.
Based on Vince Emigh's comment/answer I was led to this Oracle doc on lamda expressions and to this one on method references. I've found 3 ways to do this so far.
1) Anonymous class:
source.addMetronomeEventListener(
new MetronomeEvent() {
#Override
public void Tick(Date tickDate) {
System.out.println("anonymous class:");
System.out.println(tickDate.toString());
}
}
); // Adds itself as a listener for the event
2) Lambda expression:
source.addMetronomeEventListener(d -> System.out.println("lambda:\n"+d.toString()));
3) Method reference, which is the closest to what I am accustomed to. A method is defined in the main class:
public static void processTick(Date tickDate){
System.out.println("method reference:");
System.out.println(tickDate.toString());
}
...and then in the body of main() it is added as an event handler like this:
source.addMetronomeEventListener(MainApp::processTick);

Java Class.forName method java.lang.ClassNotFoundException;

I've found other thread where people had and solved this error; however, all of were NOT using fully qualified class paths. I cannot seem to get Class.forName to work and I am using fully qualified paths.
I've tested compiling from CLI and using ItelliJ Idea. Both fail with the same error.
Code (in test directory):
package test;
public class Test {
public static void main(String[] args) {
Class cls = Class.forName("java.util.ArrayList");
}
}
Error:
java.lang.ClassNotFoundException; must be caught or declared to be thrown
The example above does NOT work. Thanks in advance!
You're getting this message because ClassNotFoundException is a checked exception. This means that this exception can not be ignored. You need to either surround it with a try/catch construct and provide exception handling or add a throws clause to your method and handle it in a callee.
EDIT:
Please note that Class.forName() construct is not resolved during compilation. When you write such a statement, you're telling the JVM to look during program execution for a class which may not have been loaded. Java libraries are dynamically linked instead of statically linked, meaning that their code is not incorporated in your program code, being loaded only when requested. This is why it throws ClassNotFoundException.
Class.forName("java.util.ArrayList") method declared to throw a checked exception ClassNotFoundException, so you must handle it inside a try/catch block like following
package test;
public class Test {
public static void main(String[] args) {
try {
Class cls = Class.forName("java.util.ArrayList");
} catch (ClassNotFoundException e) {
// Handle it here
}
}
}
Try this:
try{
Class cls = Class.forName("java.util.ArrayList");
}catch(ClassNotFoundException e){
... do messaging or logging
}
or throw ClassNotFoundException in the methods signature:
public static void main(String[] args) throws ClassNotFoundException {
I don't know why none of the answers above can explain why this error happened. Neither can I, but I once encountered this issue and solved it by using
Thread.currentThread().getContextClassLoader().loadClass($YOUR_CLASS_NAME)
Hope it can solve your problem and hope someone can give us an explanation.
There are two options:
Surround with a try-catch block and do some appropriate handling:
package test;
public class Test {
public static void main(String[] args) {
try {
Class cls = Class.forName("java.util.ArrayList");
} catch(ClassNotFoundException e) {
System.out.println("This is not a very serious exception, or at least Test knows how to handle it");
}
}
}
Throw it outside the method in the hope that some calling method will know what to do.
package test;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class cls = Class.forName("java.util.ArrayList");
}
}

Categories