Advanced programming


In the chapter on business objects you learned how to create programs that can be started from the menu on a client. End users use business objects for their daily business (implemented business processes and functionalities).

On the other hand, there are ACComponent instances that exist in the application projects (or application trees ) on the server side and are also responsible for the automated handling of business and production processes. These can either be static process application instances  or dynamic workflow instances that are loaded into the application trees during runtime.

Now, as a programmer, you want to avoid programming redundant code in order to be able to map the same business process functionalities on the client or server side. In addition, there is the problem that you often have to program project-specific changes that deviate from the standard, which should also be available on the client and server side. The customer may also need communication interfaces to external systems that also want to use the common functionalities. Or you would like to make these functionalities available on mobile devices ...

The service-oriented architecture of iPlus is predestined for these requirements, because you can provide the common code with so-called manager classes, which are organized under the address "\Root\LocalServiceObjects".


You add manager classes in the development environment below "LocalServiceObjects":

 

All manager classes provided by iPlus are derived from the abstract base class " gip.core.autocomponent. PARole " and end with the word "manager". (The term " manager " was chosen because it should represent a bridge to the real world. People who want to use a service must turn to a central point in a company or the public service, eg the exhibition a passport; the salary you receive from the HR department; a work assignment that you receive from your supervisor. These central offices therefore assume a certain " role " or function in an overall system.)

So if you want to develop your own manager class, you should stick to this naming and also derive it from PARole.

We also recommend setting the start type to "If required", because it is sufficient to only instantiate the class when it is actually needed. In addition, instances in "LocalServiceObjects" cannot be persisted because each client and server instantiates these instances in its own application domain. Hence, manager classes must be stateless !

 

Programming guidelines for manager classes

  1. Since the common functions of manager classes are called from different places at the same time (multi-threading), they must not have any private fields (stateless).
  2. You have to program the class functionally . This means that all required data must be passed as parameters when the method is called. Internal method calls as well.
  3. Manager classes must therefore not be secured with thread locks because there are no private field values ​​(status).

 

 

The following example shows how to program a manager class:

 

The following method is declared in the base class PARole: 

public static T GetServiceInstance<T>(ACComponent requester, string acIdentifier, CreationBehaviour creationBehaviour = CreationBehaviour.Default) where T : IACComponent

This static helper method returns the instance of any manager class. It searches for the instance in the following order:

  1. Below the requesting component itself (child). If it wasn't found there, then it will 
  2. searched below "\ Root \ LocalServiceObjects" . If it wasn't found there, then it will
  3. searched in the application project "\ Services" (network instance)

In the example code above, two methods (A) and (B) have been declared that use the GetServiceInstance <T> method. In your manager class that you want to program, however, you have to decide whether it should be available locally (A) or as a network service (B). Both as in the example above are not possible.

The other two methods (C) and ( D ) use GetServiceInstance () and create a smart pointer ACRef <T> .

The "SumLines ()" (E) method is intended for local use. Please note that all necessary data must be transferred as parameters because manager classes must be stateless.

The "SumLinesByID" (F) method is intended for use in a network.

 

Now let's look at how this "manager class" is used:

 

If you want to use your manager class locally , then you should program it as in the example under points (A) and (C) . To use it as a network-compatible instance, program it as described in points (B) and (D) .

Don't forget  to disconnect the  smart pointer in the deinitialization phase (E) .


The best-known manager class is the number generator ( gip.core.autocomponent. ACVBNoManager ), which you already got to know when programming a New () method for a business object. The number generator is created under "LocalServiceObjects". Because it is needed very often, it can be accessed directly via the " IRoot .NoManager " auxiliary property . Since it is programmed stateless, all necessary data must be transferred via parameters:

string secondaryKey = Root.NoManager.GetNewNo(Database, typeof(InOrder), InOrder.NoColumnName, InOrder.FormatNewNo, this);
CurrentInOrder = InOrder.NewACObject(DatabaseApp, null, secondaryKey);

GetNewNo is a virtual method and has the following signature:

public virtual string GetNewNo(IACEntityObjectContext context, Type type, string entityNoFieldName, string formatNewNo, IACComponent invoker = null)

You can override this method in a derivation for project-specific behavior. In order for your class to be used, swap the class using the context menu in the development environment:

 

You can set the number range that the number generator should use in the " gip.bso.mes. BSONoConfiguration " business object .