Problem following example in chapter 3 of jmonkey3.0 begginer`s guide book

Hi, in the chapter 3 of this book i am doinf the example for CubeChaserState, and in that example when you extends AbstractAppSate tells you to mark:
private final Camera cam;
private final Node rootNode;

both as final, but then in the initialize method you have to assing them a value:
this.cam = this.app.getCamera();
this.rootNode = this.app.getRootNode();
so the compiler marks the error you can assign a value to a final variable, What i have to do to solve it? because if i don´t mark that fields as final the code doesn´t seem to work properly

@jor1980 said: because if i don´t mark that fields as final the code doesn´t seem to work properly

We’ll need more description than that. It could mean so many different things.

Please post the source code, as others in the forum here does not necessarily have the guide.

Here is the code, deleting the final descriptor of the fields camera and rootNode the code works properly, so i want to know why the book saids that those fields must be final:
[java]package mygame;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.collision.CollisionResults;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;

/**
*

  • @author Jorge
    */
    public class CubeChaserState extends AbstractAppState {
    private SimpleApplication app;
    private final Camera cam;
    private final Node rootNode;
    private AssetManager assetManager;
    private Ray ray = new Ray();
    private static Box mesh = new Box(Vector3f.ZERO, 1, 1, 1);
    private int counter=0;

    public int getCounter() { return counter; }

    @Override
    public void initialize(AppStateManager stateManager, Application app) {
    super.initialize(stateManager, app);
    //TODO: initialize your AppState, e.g. attach spatials to rootNode
    //this is called on the OpenGL thread after the AppState has been attached

     super.initialize(stateManager, app);
     this.app = (SimpleApplication) app;
     this.cam = this.app.getCamera();
     this.rootNode = this.app.getRootNode();
     this.assetManager = this.app.getAssetManager();
     makeCubes(40);
    

    }

    @Override
    public void update(float tpf) {
    //TODO: implement behavior during runtime

     CollisionResults results = new CollisionResults();
     ray.setOrigin(cam.getLocation());
     ray.setDirection(cam.getDirection());
     rootNode.collideWith(ray, results);
     if (results.size() > 0) {
         Geometry target = results.getClosestCollision().getGeometry();
         if (target.getControl(CubeChaserControl.class) != null) {
             if (cam.getLocation().
                 distance(target.getLocalTranslation()) < 10) {
                 target.move(cam.getDirection());
                 System.out.println(
                 target.getControl(CubeChaserControl.class).hello()
                 + " and I am running away from " + cam.getLocation() );
                 counter++;
             }
         }
     }
    

    }

    @Override
    public void cleanup() {
    super.cleanup();
    //TODO: clean up what you initialized in the initialize method,
    //e.g. remove all spatials from rootNode
    //this is called on the OpenGL thread after the AppState has been detached
    }

    public Geometry myBox(String name, Vector3f loc, ColorRGBA color)
    {
    Geometry geom = new Geometry(name, mesh);
    Material mat = new Material(assetManager,
    “Common/MatDefs/Misc/Unshaded.j3md”);
    mat.setColor(“Color”, color);
    geom.setMaterial(mat);
    geom.setLocalTranslation(loc);
    return geom;
    }
    private void makeCubes(int number) {
    for (int i = 0; i < number; i++) {
    // randomize 3D coordinates
    Vector3f loc = new Vector3f(
    FastMath.nextRandomInt(-20, 20),
    FastMath.nextRandomInt(-20, 20),
    FastMath.nextRandomInt(-20, 20));
    Geometry geom = myBox(“Cube” + i, loc, ColorRGBA.randomColor());
    if (FastMath.nextRandomInt(1, 4) == 4) {
    geom.addControl(new CubeChaserControl(cam, rootNode));
    }
    rootNode.attachChild(geom);
    }
    }
    }[/java]

Well as it seesm that final there cannot be, as then you would need to set the values in the constructor.

What is the not working behaviour when you just remove the final? As this should not change any logic.

I would say you should se 40 boxes around the center point, with about 25% beings chasers (whatever that means)

Then if you look at a cube and are near to it, it should do a ray test and tell you if it is running away from the camera

@jor1980 said: Here is the code, deleting the final descriptor of the fields camera and rootNode the code works properly, so i want to know why the book saids that those fields must be final:

Because the book has a mistake. You said in your first post that removing final caused other things to fail… if so then that would be the real issue. But now you say that when you remove final everything works.

Either way, those “final” keywords are incorrect there.

I was wrong about the error, i thought that the code doesn´t work correctly but removing the final it works 100% right.