Writing Your First IFS Cloud Projection from Scratch

Writing Your First IFS Cloud Projection from Scratch

A step-by-step guide to modeling a new entity in IFS Developer Studio, writing the projection, and surfacing it in Aurena — covering Marble syntax, entity keys, and deployment.

IFSIFS CloudDevelopmentMarbleProjectionsDeveloper Studio

Projections are the bridge between IFS Cloud's powerful back-end logic and the modern IFS Cloud Web/Aurena client. They publish modelled business services through IFS's OData-based REST API, making approved data and operations accessible to pages and integrations. In this guide, we'll walk through creating your first projection from the ground up—from modeling an entity in Developer Studio to deploying it in a dev environment.

Understanding IFS Projections

Before we dive into code, let's clarify what a projection does and where it fits in the IFS architecture.

What is a Projection?

A projection is a model that exposes functional business logic from IFS Cloud as a RESTful web service. It acts as an abstraction layer between the database (where your core entities live) and the client UI. The projection:

  • Shields the client from direct database access
  • Enriches the data with runtime logic and calculated fields
  • Enforces business rules at the service layer
  • Defines entry points via entitysets that clients consume
  • Optionally includes PL/SQL logic for server-side operations

Think of it as a carefully curated view of your entity that includes only what the UI needs, plus any derived or computed fields.

The Layered Architecture

IFS Cloud uses a Layered Application Architecture (LAA) to keep customizations separate from the core product. IFS-delivered components can contain Base/Core source, while extension/customer layers are used according to the solution ownership and development model:

  • Core Layer – IFS-provided standard functionality
  • Extension (Ext) Layer – For extensions and enhancements
  • Customization (Cust) Layer – For customer-specific modifications

When you write your own projection, you typically work in the Cust or Ext layer. This keeps the change separate from IFS-delivered Core source and makes upgrade analysis and conflict handling much clearer.

Project Structure: File Types and Dependencies

IFS Aurena development involves four interconnected source areas:

1. Entity and Enumeration Models (.entity and .enumeration)

The persistent business object is modelled first. These are Developer Studio server-model files: use the entity and enumeration editors to define keys, attributes, references, persistence and state. The projection consumes the generated entity; it does not redefine the table model inline.

2. Projection File (.projection)

The projection file defines the data structure and operations. It contains:

  • Entitysets – Which generated entities or queries to publish
  • Datasources – Entity, query, summary, structure, and virtual definitions exposed by the service
  • References – Related entities that can be fetched
  • Arrays – Collections of child records
  • Actions & Functions – Operations the client can invoke
  • Calculated data items – Projection-specific fetched or virtual values
  • Enumeration references – Domain values already defined in the model

3. Projection Service and Entity PL/SQL (.plsvc and .plsql)

Developer Studio generates the projection's _SVC package and the implementation signatures for declared operations. Depending on the release and development workflow, projection-specific implementations are exposed as PL/SQL service (.plsvc) source or as a generated service implementation scaffold. Entity-owned rules and reusable business APIs remain in the owning entity's layered .plsql source. Together they cover:

  • Custom action logic
  • Function implementations
  • Method overrides
  • Server-side validation

Generate after declaring an action or function, then implement the exact scaffold produced for the target release. Do not hand-create an _SVC package or assume that an Apps 10, early Cloud, and current Cloud workspace will present the service source in exactly the same way.

4. Client File (.client)

The client file defines the UI structure (pages, lists, dialogs). For this guide, we'll focus on projections, but the client depends on the projection for its data source.

Dependencies

When you commit a projection:

  1. The projection depends on entities – You must reference existing database entities
  2. If entities have enumerations, the projection depends on those
  3. The client depends on the projection – The UI binds to projection data
  4. During build, the code generator traverses these dependencies to validate everything is in place

Source grammar and generated extension points can vary between released IFS Cloud versions. Keep examples that are valid for the release you support, and always validate them with that release's Developer Studio.

Step 1: Understand Your Entity Model

Before writing the projection, you need to know your underlying entity. In this example, we'll create a projection for a hypothetical EmployeeBonus entity.

Typical Entity Structure

An entity in IFS Cloud has:

  • Primary Keys – Unique identifiers (often composite)
  • Attributes – Data fields with types
  • References – Links to parent entities
  • Derived Values – Calculated or fetched fields

For our EmployeeBonus example, create these attributes in the entity model rather than in the projection:

AttributeModel typePurpose
BonusIdTEXTStable business key
EmployeeIdTEXTReference to Employee entity
DepartmentIdTEXTReference to Department entity
BonusAmountNUMBERThe bonus value
TaxAmountNUMBERTax withheld from the bonus
BonusDateDATEWhen the bonus was awarded
ApprovedByTEXTManager who approved it
NotesTEXTAdditional details
StatusEnumeration modelDraft, Approved, Paid

Step 2: Create the Projection File in Developer Studio

Open IFS Developer Studio and follow these steps:

Create a New Projection

  1. Right-click on the registered customer component that owns the feature
  2. New > Projection
  3. Name: EmployeeBonus (descriptive, globally unique)
  4. Layer: Use the layer appropriate to that component and customer solution; do not modify IFS-delivered Core source
  5. Component: Select the real owning component (the examples use the placeholder BONUS)
  6. Description: "Projection for managing employee bonuses"

Set the Category and Dependency


Step 3: Write the Projection Marble Code

Now, let's build out the projection structure. Here's a complete example:


Understanding Entitysets

An entityset is the REST endpoint exposed by your projection. It maps to a specific entity and defines how it's queried:


@DynamicComponentDependency COMPONENT has a narrower purpose: it conditionally includes decorated source when an optional component is installed. It does not load arbitrary entities at runtime. Use a normal component dependency when the projection cannot function without the referenced component.

Attribute Types and Annotations

Marble supports several attribute types and modifiers:

TypeUsageExample
TextText valuesattribute Name Text;
IntegerWhole numbersattribute Count Integer;
NumberNumeric valuesattribute Amount Number;
DateCalendar datesattribute BonusDate Date;
TimestampDate and time valuesattribute CreatedAt Timestamp;
BooleanTrue/Falseattribute IsActive Boolean;
EnumerationFixed domain valueattribute Status Enumeration(BonusStatus);

Key modifiers:

  • required = [true] – Marks a projection data item as required
  • updatable = [false] – Prevents the projection item being updated
  • label = "Display Name" – Supplies a human-readable label
  • fetch = "..." – Supplies a database expression for a calculated item

Entity keys and mandatory persistent attributes are defined in the entity model, not invented with inline is key syntax in the projection.

Key Marble Syntax Explained

@DynamicComponentDependency – Makes a section conditional on an optional installed component.

entity – Alters or enriches the generated projection entity when explicitly declared.

attribute – A field from the underlying database entity or a computed value.

reference – A link to another entity. This creates a relationship that can be navigated from the client.

array – A collection of child records (similar to a one-to-many relationship).

virtual or fetched attribute – Projection data calculated at runtime; not stored directly.

action – A server-side operation the client can invoke (like "ApproveBonus").

function – A callable operation that returns a value.

enumeration – A fixed domain modelled separately and referenced by the entity or projection.

structure – A complex data type returned by functions, not a main entity.

Step 4: Using @Override for Customizations

When you're working in the Cust layer and customizing an existing projection, you use @Override to modify only the parts you're changing.

Example: Adding a Field to an Existing Projection


That example assumes the entity customization has already added the corresponding company_bonus_code persistence. For a calculated item, use a supported SQL expression or API call in fetch instead.

Key Points:

  • Only include the attributes/actions you're adding or modifying
  • Use @Override on the entity itself
  • Use the target release's documented @Override grammar for individual model elements
  • The generator merges the customer layer with the lower layer during code generation
  • Never modify Core-layer files directly

Step 5: Working with References and Arrays

Projections aren't isolated—they often reference other entities. Understanding how to properly define and use references is critical.

One-to-One References


When a client requests an EmployeeBonus, they can expand the EmployeeRef to get the full Employee record:

GET /EmployeeBonuses(BonusId='B123')?$expand=EmployeeRef

This returns the bonus plus all Employee attributes in one response.

One-to-Many Arrays

Arrays represent child collections:


If the same projection also publishes entityset Employees for Employee;, you can include the bonuses when querying an employee:

GET /Employees(EmployeeId='E001')?$expand=Bonuses

Lazy Loading vs. Eager Loading

By default, references and arrays use lazy loading – they're not included unless explicitly requested via $expand. This improves performance for large datasets.

Use $expand only where the published relationship and use case justify it:


Avoid expanding a high-cardinality child collection for every row in a large list. Fetch the detail collection when the user opens the record instead.

Step 6: Define Entity Keys and Search Predicates

Entity keys are critical for REST operations. They uniquely identify records and form the URL path.

Simple vs. Composite Keys

Simple Key (one attribute) is defined on BonusId in the entity model. Inspect $metadata to see its projection property name and OData type.

Composite Key (multiple attributes):

For a composite key, mark both EmployeeId and BonusYear as keys in the entity model and preserve their generated order.

When composite, the URL would look like:

/EmployeeBonuses(EmployeeId='E001',BonusYear=2025)

Search Predicates

You can define how records are filtered:


The predicate is a server-side database expression. Confirm the stored enumeration value and generated column name. Apply user-specific date filters and ordering through supported OData query options rather than embedding $today or an order by clause in this block.

Step 7: Implement the Generated Server Extension Point

When an action or function needs custom logic, generate the affected model and inspect the exact implementation scaffold produced for that release. In Developer Studio workflows that provide projection PL/SQL service source, implement the generated method in the .plsvc source. Keep entity-owned validation and reusable business behaviour in the entity's layered .plsql source or a published IFS API. Never edit the generated database package body directly.

The approval implementation should:

  1. Load the selected record using its generated key.
  2. Lock or apply optimistic-concurrency handling as the entity pattern requires.
  3. Confirm the caller is allowed to perform the business transition.
  4. Reject a record that is no longer in Draft state.
  5. Apply the state change through the generated entity logic or a supported IFS API.
  6. Record the approval note and audit data through the same business transaction.

Use the IFS error framework for a business validation, for example inside the generated package context:


The surrounding procedure name and parameters must come from the generated action scaffold. Do not guess them from the REST action name.

When overriding an existing generated method, layered PL/SQL uses super to retain lower-layer behaviour:


That example shows the layering pattern, not the approval action itself. A new generated action implementation will have its own signature.

Transaction Ownership

Projection actions run inside a framework-managed transaction. On success the service transaction commits; on failure it rolls back. Do not place COMMIT or ROLLBACK inside the action implementation. Manual transaction control can make part of a failed business operation permanent and can break retry behaviour.

Avoid Direct Table DML

Do not update a standard _TAB table or create a hand-made approval log as a shortcut. Direct DML bypasses entity validation, state events, history, accounting, integrations, and other side effects. Use the generated entity methods and published business APIs. For a customer-owned entity, model required audit attributes or a related audit entity so they are generated and delivered with the feature.

Actions and Functions

An action may change database state. A function must not. A net-amount calculation can be a fetched attribute or a function if several clients need it; approval must be an action. Bound operations are preferred. An unbound operation should specify an initialcheck so authorisation is established before execution.

Step 8: Code Generation and Compilation

Build and Generate

  1. Save your projection file (.projection)
  2. Save the affected entity, enumeration, projection, client, projection-service implementation, and layered .plsql source
  3. In Developer Studio: Right-click your component > Build or Generate Code

The build process creates:

  • Generated database and projection implementation artefacts
  • OData service metadata for the projection
  • Client metadata consumed by IFS Cloud Web

Monitor the Build Log

Check Developer Studio validation first, then the authoritative Build Place and delivery logs for the target environment. Log names differ across releases and build arrangements.

Common issues:

  • Entity not found – Check the referenced entity exists
  • Syntax errors – Verify Marble syntax (matching brackets, semicolons)
  • Package compile errors – Check the generated log and the affected layered .plsql source

Step 9: Build and Deliver to a Development Environment

Once local validation is successful, the source must be built and delivered through the customer's supported IFS Cloud lifecycle.

Deployment Steps

  1. Commit the complete source change – Include the models and layered server source in the customer solution repository.
  2. Create a build – Use IFS Lifecycle Experience/Build Place for the release-aligned customer solution.
  3. Review failures and warnings – Resolve generation, dependency, compile, and static-analysis issues.
  4. Create a delivery – Promote the immutable build through the agreed non-production delivery stages.
  5. Apply change control – Record permissions, configuration, test evidence, and rollback/recovery planning with the delivery.

Verify Deployment

For IFS-managed Cloud environments, verify deployment through build and delivery logs, API Explorer, the projection's $metadata, page behaviour, and supported logs. Customers do not normally connect as the application owner to query USER_OBJECTS. Some remote or customer-managed arrangements provide database access, but a database object check is not a substitute for testing the published service and permissions.

In Apps 10 or a customer-managed development environment where application-owner database access is explicitly supported, a read-only object check can supplement those tests:


Use the actual generated package name from the build output; do not infer it solely from the projection display name.

Step 10: Surfacing the Projection in Aurena

Now that your projection is available in the development environment, the final build step is creating a Client file to expose it in Aurena.

Create a Client File

EmployeeBonus.client:


Pages and Navigation

  • The page contains all UI elements for a business process
  • Selectors let users choose a record or context
  • Groups display a single record's detailed information
  • Commands call projection operations or perform supported client navigation and dialog behaviour
  • Fields bind to projection attributes

The client names its projection explicitly. Add the approval command only after the action is present in generated metadata; calls use the parameters and binding produced for the target release, not a JavaScript or SQL block embedded in the client.

Step 11: Testing and Validation

Test via Aurena UI

  1. Log into your Aurena environment
  2. Navigate to the entry you added for the page; the projection category does not create a navigator entry by itself
  3. Verify you can:
    • List bonuses
    • View details
    • Invoke the Approve action
    • See calculated fields update

Test via REST API

You can also test directly via the OData endpoint:


Obtain the short-lived access token through an approved IFS IAM client and OAuth flow; do not put a username and password in source or shell history. Keep shell tracing disabled while handling the token. Passing the generated authorization header through stdin keeps the token out of curl's process arguments. Replace Approved with the literal exposed by the deployed enumeration contract. A bound action is called with POST, but its namespace-qualified path, body, key syntax, and ETag requirements must come from $metadata for the deployed release.

Validate the Published Contract, Not Just the Happy Path

The page working for an administrator is only the first test. Before promoting the projection, exercise the contract with a user who has exactly the intended permission set and record access:

  1. Read $metadata and retain it with the test evidence. Check entity-set names, key order/types, nullability, operation binding, return structure, and enumeration values.
  2. Query one page with $select and a bounded $top; then follow every server-provided @odata.nextLink until the test set is complete.
  3. Test an allowed filter, sort, reference expansion, and composite key using the exact property casing in metadata.
  4. Create or update a test record only in an approved non-production data set. Send the concurrency token/ETag required by that entity and prove that a stale update is rejected.
  5. Invoke the action as an authorised user, an unauthorised user, and against a record in the wrong lifecycle state.
  6. Confirm that a failed action leaves no partial business update or outbound side effect.
  7. Verify that fields excluded for security are absent from metadata/response, rather than merely hidden on the page.
  8. Repeat the core tests through the intended integration identity; an interactive administrator token can conceal missing grants.

A compact promotion record might look like this:

Contract areaEvidence
Service identityProjection name, versioned base URL, build/delivery ID
Data shapeCaptured $metadata and approved response sample with sensitive values removed
AuthorisationPermission-set grant plus allowed/denied test results
Business accessCompany/site/user data-scope tests
ConcurrencyCurrent ETag succeeds; stale ETag fails without overwrite
TransactionValidation failure produces no partial state change
PerformanceRepresentative $select, $filter, $expand, and paging timings

This evidence becomes especially valuable after an IFS update. If metadata, generated operation signatures, or enumeration literals change, you can see the contract delta before a client or integration fails in production.

Best Practices and Key Takeaways

1. Keep Projections Lean

Don't expose every attribute of an entity. Include only what the UI needs. This improves performance and security.

2. Use References Wisely

References are powerful but can cause performance issues if overused. Prefer explicit selection over automatic fetching.

3. Separate Core and Customization

Use Cust when extending IFS-delivered source, and the owning layer defined for a registered customer component when developing new customer-owned source. Keep the ownership boundary explicit so upgrades can analyse it.

4. Test Early and Often

Generate and build frequently during development. Catch syntax errors before they accumulate.

5. Document Your Marble

Add descriptions and comments:


6. Validate on the Server

Put authoritative business rules in the entity or service layer and raise a meaningful IFS business error, ensuring consistency across all clients. A client enabled expression is not enforcement.

7. Version and Track Changes

Use clear naming and comments in your projection files. When you create a new version, increment version numbers or add timestamps.


Treat these comments as human-readable context; the customer solution repository and immutable build/delivery identifiers remain the source of truth.

Conclusion

Creating a projection is the gateway to modern IFS Cloud development. By following this step-by-step guide, you've learned how to:

  1. Model an entity in IFS terminology
  2. Write Marble syntax for projection definitions
  3. Use @Override for customizations in the Cust layer
  4. Implement business logic in the generated projection-service extension point and supported layered .plsql source
  5. Generate and build your projection
  6. Deploy to dev and test in Aurena

Projections are the bridge between database and UI. Master them, and you unlock the full power of IFS Cloud customization. The patterns you've learned here—entity modeling, layered architecture, action and function definitions—apply to every projection you'll create.

Now it's your turn. Start with a simple entity, build your projection, and watch it come to life in Aurena. Happy coding!


Further Reading

Need support building your first IFS Cloud projection?

Syrett Consultancy can help your team model entities, structure projections, and avoid the common first-project mistakes.