Documentation

Trace:

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
jvx:server:lco:actions_in_objects [2018/02/01 22:53]
admin
jvx:server:lco:actions_in_objects [2020/07/08 17:52] (current)
cduncan articles
Line 1: Line 1:
-~~Title: ​Working with server-side actions~~+~~NOTRANS~~ 
 +~~Title: ​Actions in Server Objects~~
  
-[[jvx:communication:calling_server_action|server-side action]] ​is a simple Java method ​defined in a [[jvx:​server:​lco:​lifecycle|life-cycle object]] (LCO). A standard JVx application has an application global LCOa Session LCO and a LCO for every screen.+Every [[jvx:server:lco:actions|server-side action]] ​should be defined in a [[jvx:​server:​lco:​lifecycle|life cycle object]] (LCO). ​Sometimesit's better to group functionality in helper objects.
  
-An action can be defined in every LCO, but it makes sense to define the actions ​in the right "​context" ​and for the right "​scope"​. But what is the right scope?+It's very easy to encapsulate functionality ​in objects. Just create an object ​and add public methods:
  
-Start defining your actions in screen LCOs and if an action is re-usable, move it to the Session LCO. The application LCO is not a relevant context for actions because it makes no difference if you define an action in the application LCO or session LCO. The application LCO exists exactly once for an application. The session LCO will be created for every Master connection (= user login). The application LCO can be used to store "​application global"​ objects or states.+<file java Car.java> 
 +public class Car 
 +
 +    private String type; 
 +    private int speed;
  
-The general rule is that the screen LCO should be the first place for your actions and the session LCO should be used for re-usable actionsBut be careful because there are some things to know!+    public Car(String type, int speed) 
 +    { 
 +        this.type = type; 
 +        this.speed = speed; 
 +    }
  
-You application usually ​has following ​classes:+    public String getType() 
 +    { 
 +        return sType; 
 +    } 
 + 
 +    public int getSpeed() 
 +    { 
 +         ​return speed; 
 +    } 
 +
 +</​file>​ 
 + 
 +Our Car class has two methods: **getType** and **getSpeed**! 
 + 
 +If you're using the Car class in your life cycle object, like the following:
  
 <file java> <file java>
Line 20: Line 43:
 public class Session extends Application public class Session extends Application
 { {
-+    ​public ​Car getCar()
- +
-// A Screen LCO +
-public ​class Students extends Session +
-+
-+
-</​file>​ +
- +
-The Students LCO extends the Session LCO and the Session LCO extends the Application LCO. This class hierarchy makes it possible to call actions from the super class, e.g. +
- +
-<file java Session.java>​ +
-// Session LCO +
-public class Session extends Application +
-+
-    public CachedObject getContacts()+
     {     {
-        ​CachedObject obj = (CachedObject)get("contacts");+        ​Car car = (Car)get("car");
  
-        if (obj == null)+        if (car == null)
         {         {
-            ​obj = new CachedObject(); +            ​car = new Car();
-            obj.setId("​contacts"​);+
  
-            put("contacts", ​obj);+            put("car", ​car);
         }         }
-    ​ + 
-        return ​obj;+        return ​car;
     }     }
-    ​ 
-    public void sendAlert(String pMessage) 
-    { 
-        Mail.send("​noreply@sibvisions.com",​ "​alert@customer.com", ​ 
-                   null, "Alert from EG", pMessage); 
-    } 
-} 
- 
-// A Screen LCO 
-public class Students extends Session 
-{ 
 } }
 </​file>​ </​file>​
  
-It'​s ​possible to call the sendAlert action through the Students LCO because the method was defined in the super class - Session - and it's a public method. This is possible because of the class hierarchy+it will be possible to call getType ​and getSpeed
  
-{{:​jvx:​server:​lco:​lco_class.png?​nolink|}}+<file java> 
 +connection.call("​car",​ "​getSpeed"​) 
 +</​file>​
  
-But if you call the action, it will be called in the Session LCO instance and not in the Students LCO instance//What?//+But this call would throw a SecurityException with "​access is not allowed"​.
  
-The Students LCO has a parent LCO and this is the Session LCOThe Session LCO has the Application LCO as parentThe Application LCO doesn'​t have a parent:+It's not possible to call every method of an object just because it's publicThis could open back doors.
  
-{{:jvx:​server:​lco:​lco_parents.png?​nolink|}}+You have to define accessible methods - from objects - via annotation:
  
-The parents will be set automatically from the ObjectProvider,​ but only if your LCOs are an instance of GenericBean,​ which is preferred. It would be possible to create your LCOs as instance of Map interface, but you would lose many advantages like object caching. The LCOs in our example are GenericBean instances! +<​file ​java Car.java> 
- +public class Car
-== Why does JVx set a parent LCO? == +
- +
-Simple answer: to save memory and object instances. +
- +
-All objects in the Application LCO exist only once - like singletons per application. All objects in the Session LCO exist only once per user. All objects in the Screen LCOs like Students, exist for every screen instance. +
- +
-If you close a screen, all Screen LCO instances will be discarded and if you logout from the application,​ all Session LCO instances will be discarded. This mechanism helps to reduce the memory consumption but it adds complexity to your LCOs. +
- +
-The Students LCO extends the Session LCO and all public/​protected/​package private methods of the Session LCO are available in the Students LCO. But if you access an object like contacts via getContacts,​ you will get the instance from the Session LCO and not a new instance from the Students LCO. If you overwrite the method in the Students LCO, you will receive a new instance of the object for your LCO and not the instance from the Session LCO. This is a built-in security mechanism and a sort of object scope.  +
- +
-The only thing you should really know is that a call or an object access will use the LCO where the method was declared. +
- +
-In most cases, the standard mechanism works like a charm, but sometimes you need more control. Imagine you have 3 screens and every screen has the same actions. You would define all actions in the Session LCO because they are re-usable. But all actions are stateful and save a timestamp in a field property: +
- +
-<file java> +
-// Application LCO +
-public class Application extends GenericBean+
 { {
-}+    ...
  
-// Session LCO +    @Accessible 
-public class Session extends Application +    public String ​getType()
-+
-    private Date date; +
-    ​ +
-    public String ​openAccount()+
     {     {
-        ​date = new Date(); +        return ​sType;
-         +
-        ​return ​UUID.randomUUID().toString();+
     }     }
-    ​ + 
-    public ​Date getOpenDate()+    @Accessible 
 +    public ​int getSpeed()
     {     {
-        ​return ​date; +         return ​speed;
-    } +
-     +
-    public void releaseAccount() +
-    { +
-        date = null;+
     }     }
 } }
 +</​file>​
  
-// A Screen LCO +The call:
-public class Students extends Session +
-+
-}+
  
-// A Screen LCO +<file java> 
-public class Teacher extends Session +connection.call("​car",​ "​getSpeed"​);​
-+
-}+
 </​file>​ </​file>​
  
-If you call the openAccount action via Students LCO, the Session LCO will be used and the date field will be saved in Session LCO. If you call the same action via Teacher LCO, the Session LCO will be used and the same date field will be used. This is not good because the Screen LCOs are not independent from each other!+will work without problems!
  
-One possible solution could be that you move all re-usable screen actions to placeholder class:+If you define ​public method in your LCO (action), it's always accessible because, usually, you will offer business logic or storages for the client. But it's possible to deny the access to objects or actions:
  
-<file java+<file java Session.java>
-// Session ​LCO+
 public class Session extends Application public class Session extends Application
 { {
-+    @NotAccessible 
- +    public ​getCar()
-// placeholder class for actions +
-public class AccountSession extends Session +
-+
-    private Date date; +
-    ​ +
-    public ​String openAccount()+
     {     {
-        ​date = new Date(); +        ...
-         +
-        return UUID.randomUUID().toString();+
     }     }
-    ​ 
-    public Date getOpenDate() 
-    { 
-        return date; 
-    } 
-    ​ 
-    public void releaseAccount() 
-    { 
-        date = null; 
-    } 
-} 
- 
-// A Screen LCO 
-public class Students extends AccountSession 
-{ 
-} 
- 
-// A Screen LCO 
-public class Teacher extends AccountSession 
-{ 
 } }
 </​file>​ </​file>​
  
-If you call the openAccount action, the date field will be saved in Students or Teacher LCO, because the placeholder class is not the Session LCO and everything will work as expected. The Screen ​LCOs are independent from each other. +The **NotAccessible** annotation denies the access via connection ​call but it's still possible to invoke ​the method directly ​in your Session LCO or a Screen ​LCO:
- +
-This solution needs an extra class to work-around the built-in call mechanism of JVx. But there'​s a built-in solution without placeholder class:+
  
 <file java> <file java>
-// Session LCO 
 public class Session extends Application public class Session extends Application
 { {
-    ​private Date date; +    @NotAccessible 
- +    public ​getCar()
-    ​@Inherit +
-    public ​String openAccount()+
     {     {
-        ​date = new Date(); +        ...
-         +
-        return UUID.randomUUID().toString();+
     }     }
-     + 
-    @Inherit +    public ​int getSpeed()
-    public ​Date getOpenDate()+
     {     {
-        return ​date; +        return ​getCar().getSpeed();
-    } +
-     +
-    @Inherit +
-    public void releaseAccount() +
-    { +
-        date = null;+
     }     }
 } }
  
-// A Screen LCO +public class Screen ​extends Session
-public class Students ​extends Session+
 { {
 +    public String getType()
 +    {
 +        return getCar().getType();​
 +    }
 } }
 +</​file>​
  
-// A Screen LCO +The call: 
-public class Teacher extends Session + 
-{ +<file java> 
-}+connection.call("​car",​ "​getSpeed"​)
 </​file>​ </​file>​
  
-All action methods are annotated ​with @InheritThis annotation defines that the action call will be done in the context of the caller LCO. The annotation ​doesn'​t ​really move the scope from Session to Screen, but it has the same effect.+will fail with a SecurityException because car object is not accessibleThe action call
 + 
 +<file java> 
 +connection.callAction("​getSpeed"​) 
 +</​file>​ 
 + 
 +will work without problems. 
 + 
 +The security controller ​doesn'​t ​check simple method calls because ​the developer should have the freedom to do everything on server side.
This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information