Setup IIB Logging in 10 minutes

Are you using log4j or any custom subflow to capture the IN and OUT messages but looking for a simple solution which can

  • captures all messages, not just IN & OUT but also exception message
  • captures the header values, environment values etc
  • does not need you to add subflows or log4j node
  • works with simple configuration like enabling monitoring profile and that’s it
  • automatically creates the log based on Node/ServerName/FlowName

A simple flow like this does all the magic for you.

IIB Transaction Monitor Flow
MQTT properties
UDP to specify Log4j config file location
2021-04-11 19:05:14.889 [Thread-30] INFO  - ----------------------------------------Transaction Starts---------------------------------------------------------
2021-04-11 19:05:14.889 [Thread-30] INFO  - Event Number :1
2021-04-11 19:05:14.889 [Thread-30] INFO  - Data Element Name :MQMD
2021-04-11 19:05:14.889 [Thread-30] INFO  - ***********************************************************************
2021-04-11 19:05:14.889 [Thread-30] INFO  - SourceQueue : IN.Q
2021-04-11 19:05:14.889 [Thread-30] INFO  - Transactional : true
2021-04-11 19:05:14.889 [Thread-30] INFO  - Encoding : 273
2021-04-11 19:05:14.889 [Thread-30] INFO  - CodedCharSetId : 1208
2021-04-11 19:05:14.889 [Thread-30] INFO  - Format : MQSTR   
2021-04-11 19:05:14.889 [Thread-30] INFO  - Version : 2
2021-04-11 19:05:14.905 [Thread-30] INFO  - Report : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - MsgType : 8
2021-04-11 19:05:14.905 [Thread-30] INFO  - Expiry : -1
2021-04-11 19:05:14.905 [Thread-30] INFO  - Feedback : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - Priority : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - Persistence : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - MsgId : 414d5120494942763130514d475220204064d15e10000105
2021-04-11 19:05:14.905 [Thread-30] INFO  - CorrelId : 000000000000000000000000000000000000000000000000
2021-04-11 19:05:14.905 [Thread-30] INFO  - BackoutCount : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - ReplyToQ :                                                 
2021-04-11 19:05:14.905 [Thread-30] INFO  - ReplyToQMgr : IIBv10QMGR                                      
2021-04-11 19:05:14.905 [Thread-30] INFO  - UserIdentifier : vaithu      
2021-04-11 19:05:14.905 [Thread-30] INFO  - AccountingToken : 160105150000002d74cc5dfa721e73431607412b32030000000000000000000b
2021-04-11 19:05:14.905 [Thread-30] INFO  - ApplIdentityData :                                 
2021-04-11 19:05:14.905 [Thread-30] INFO  - PutApplType : 28
2021-04-11 19:05:14.905 [Thread-30] INFO  - PutApplName : vaithu
2021-04-11 19:05:14.905 [Thread-30] INFO  - PutDate : 2020-06-01
2021-04-11 19:05:14.905 [Thread-30] INFO  - PutTime : 02:02:32.480
2021-04-11 19:05:14.905 [Thread-30] INFO  - ApplOriginData :     
2021-04-11 19:05:14.905 [Thread-30] INFO  - GroupId : 000000000000000000000000000000000000000000000000
2021-04-11 19:05:14.905 [Thread-30] INFO  - MsgSeqNumber : 1
2021-04-11 19:05:14.905 [Thread-30] INFO  - Offset : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - MsgFlags : 0
2021-04-11 19:05:14.905 [Thread-30] INFO  - OriginalLength : -1
2021-04-11 19:05:14.905 [Thread-30] INFO  - ***********************************************************************
2021-04-11 19:05:14.905 [Thread-30] INFO  - OrderReceived Payload :
<Orders>
   <Order>
      <CustomerID>GREAL</CustomerID>
      <EmployeeID>6</EmployeeID>
      <OrderDate>1997-05-06T00:00:00</OrderDate>
      <RequiredDate>1997-05-20T00:00:00</RequiredDate>
      <ShipInfo ShippedDate="1997-05-09T00:00:00">
         <ShipVia>2</ShipVia>
         <Freight>3.35</Freight>
         <ShipName>Great Lakes Food Market</ShipName>
         <ShipAddress>2732 Baker Blvd.</ShipAddress>
         <ShipCity>Eugene</ShipCity>
         <ShipRegion>OR</ShipRegion>
         <ShipPostalCode>97403</ShipPostalCode>
         <ShipCountry>USA</ShipCountry>
      </ShipInfo>
   </Order>
</Orders>
2021-04-11 19:05:14.905 [Thread-30] INFO  - ----------------------------------------Transaction Ends---------------------------------------------------------

There is much more. For more info, contact us at support@vaithu.com/ WhatsApp +1 6123058684

How to read excel files using Java Compute Node

Sometimes, we need to read excel files and there is no native connector in IBM Integration Bus. So, the obvious solution is to read them using Java. The most commonly used library is Apache POI.

Here I’ve written a simple program which reads the sheets ( assuming it has a header and multiple rows) and attach them to Environment tree. The java code is

public class ReadExcel_JCN extends MbJavaComputeNode {

	public void evaluate(MbMessageAssembly inAssembly) throws MbException {
		MbOutputTerminal out = getOutputTerminal("out");

		MbMessage inMessage = inAssembly.getMessage();
		MbMessageAssembly outAssembly = null;
		try {
			// create new message as a copy of the input
			MbMessage outMessage = new MbMessage(inMessage);
			outAssembly = new MbMessageAssembly(inAssembly, outMessage);
			// ----------------------------------------------------------
			// Add user code below
			
			MbElement environment = inAssembly.getGlobalEnvironment().getRootElement();
			
			File excelFiles = new File((String) getUserDefinedAttribute("ExcelDir"));
			
			Workbook workbook = null;
			
			DataFormatter dataFormatter = new DataFormatter();
			
			List<String> headerNames = null;
			String cellValue = null;
			MbElement cellElm = null;
			
			for (File excel : excelFiles.listFiles()) {
				
				workbook = WorkbookFactory.create(excel); 
				
				for (Sheet sheet : workbook) {
					
						MbElement sheetElm = environment.createElementAsLastChild(MbElement.TYPE_NAME, sheet.getSheetName(), null);
						headerNames = new ArrayList<>();
						for (Row row : sheet) {
							
							if (row.getRowNum() != 0) {
								cellElm = sheetElm.createElementAsLastChild(MbElement.TYPE_NAME, "rows", null);
							}
							for (Cell cell : row) {
								
								cellValue = dataFormatter.formatCellValue(cell);
								if (row.getRowNum() == 0) {
									headerNames.add(cellValue);
								} else {
									
									cellElm.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, headerNames.get(cell.getColumnIndex()), cellValue);
								}
							}
						}
						
						if (sheetElm.getLastChild() == null) {
							sheetElm.detach();
						}
						
				}
				
				workbook.close();
			}
			

			// End of user code
			// ----------------------------------------------------------
		} catch (MbException e) {
			// Re-throw to allow Broker handling of MbException
			throw e;
		} catch (RuntimeException e) {
			// Re-throw to allow Broker handling of RuntimeException
			throw e;
		} catch (Exception e) {
			// Consider replacing Exception with type(s) thrown by user code
			// Example handling ensures all exceptions are re-thrown to be handled in the flow
			throw new MbUserException(this, "evaluate()", "", "", e.toString(),
					null);
		}
		// The following should only be changed
		// if not propagating message to the 'out' terminal
		out.propagate(outAssembly);

	}

}

If you’re looking for any support in IIB, please contact us support@vaithu.com.

About the Author

He has worked for various clients and developed more than 800+ message flows. He is an expert in ESQL, Java Compute Node and DFDL. If you’ve any complex code to be written in ESQL, feel free to contact him at +1 6123058684.

XML/JSON Beautifier

There are lot of online tools available in the internet for this but they say, do not put sensitive information as they’re cached on the server side. So, obviously it is not a safe place to beautify. And not all companies allow admin access to developers to install plugins for this. What’s the solution for this? Let us develop something on our own and add what ever we want.

Here is a solution developed in-house keeping in mind all IIB/ACE developers.

You can not only beautify xml/json messages but also do the following

  • Blob to string
  • String to blob
  • Base64 Encode/Decode
  • XML to JSON
  • JSON to XML
  • XPath evaluation
  • XSLT Transformation
  • Validate XML against XSD
  • XML Decoding
  • Change themes

Above all this is developed as web-application and no external dependencies. Just deploy the war file to a web-server and start using it. By default it runs on port 8080 and so you can try http://hostname:8080

Here are some screenprints to please your eyes.

XML PrettyPrint
XML to JSON conversion
Blog to String

You can download this for free for personal use. For commercial use, please contact us at support@vaithu.com.

We also do full-stack development. If you’re looking for modernizing your UI, please contact us.

Vaadin themes

By default, Vaadin use Lumo theme but it also provides multiple themes which you can customize as you need. Vaadin provides an editor here https://demo.vaadin.com/lumo-editor/ which allows you to create your theme or customize the default ones. Let us see how to use them.

  • Go to https://demo.vaadin.com/lumo-editor/
  • In the right hand side, you will see the settings to modify. Modify them as you need and finally it will show you a HTML page like
  • In Vaadin v14, importing html is not supported so you’ve to copy the lines within <custom-style><style>...</style></custom-style> and copy it to a file under styles directory like
  • Now, import this file into your Java class like
@CssImport("./styles/my-lumo-theme.css")

Reload your project and you will the difference. I modified the theme to use Material theme and here is the page after importing them into my Java class

If you need DARK theme, just two lines would make it and they are

@Theme(value = Lumo.class,variant = Lumo.DARK)
public class MainView extends AppLayout {

Note these line should go into the Main/Parent class. Let us see how the dark theme looks

Let me put here my custom-theme HTML code for reference

html {
  --lumo-size-xl: 3rem;
  --lumo-size-l: 2.5rem;
  --lumo-size-m: 2rem;
  --lumo-size-s: 1.75rem;
  --lumo-size-xs: 1.5rem;
  --lumo-space-xl: 1.75rem;
  --lumo-space-l: 1.125rem;
  --lumo-space-m: 0.5rem;
  --lumo-space-s: 0.25rem;
  --lumo-space-xs: 0.125rem;
  --lumo-font-size: 1rem;
  --lumo-font-size-xxxl: 1.75rem;
  --lumo-font-size-xxl: 1.375rem;
  --lumo-font-size-xl: 1.125rem;
  --lumo-font-size-l: 1rem;
  --lumo-font-size-m: 0.875rem;
  --lumo-font-size-s: 0.8125rem;
  --lumo-font-size-xs: 0.75rem;
  --lumo-font-size-xxs: 0.6875rem;
  --lumo-shade-5pct: rgba(26, 26, 26, 0.05);
  --lumo-shade-10pct: rgba(26, 26, 26, 0.1);
  --lumo-shade-20pct: rgba(26, 26, 26, 0.2);
  --lumo-shade-30pct: rgba(26, 26, 26, 0.3);
  --lumo-shade-40pct: rgba(26, 26, 26, 0.4);
  --lumo-shade-50pct: rgba(26, 26, 26, 0.5);
  --lumo-shade-60pct: rgba(26, 26, 26, 0.6);
  --lumo-shade-70pct: rgba(26, 26, 26, 0.7);
  --lumo-shade-80pct: rgba(26, 26, 26, 0.8);
  --lumo-shade-90pct: rgba(26, 26, 26, 0.9);
  --lumo-primary-text-color: rgb(235, 89, 5);
  --lumo-primary-color-50pct: rgba(235, 89, 5, 0.5);
  --lumo-primary-color-10pct: rgba(235, 89, 5, 0.1);
  --lumo-error-text-color: rgb(231, 24, 24);
  --lumo-error-color-50pct: rgba(231, 24, 24, 0.5);
  --lumo-error-color-10pct: rgba(231, 24, 24, 0.1);
  --lumo-success-text-color: rgb(62, 229, 170);
  --lumo-success-color-50pct: rgba(62, 229, 170, 0.5);
  --lumo-success-color-10pct: rgba(62, 229, 170, 0.1);
  --lumo-shade: hsl(0, 0%, 10%);
  --lumo-primary-color: hsl(22, 96%, 47%);
  --lumo-error-color: hsl(0, 81%, 50%);
  --lumo-success-color: hsl(159, 76%, 57%);
  --lumo-success-contrast-color: hsl(159, 29%, 10%);
}

[theme~="dark"] {
}

We also started working on Full stack development using Vaadin. If you’ve any projects to develop in Vaadin, please contact us at support@vaithu.com

Cryptography in IIB

Not often but sometimes, there is a need to encrypt and decrypt messages flowing through IBM Integration Bus and there are some working solutions available in the market to achieve the same.

Since these algorithms are not available by default in ESQL, the next immediate solution is Java. So, if you are comfortable with Java Compute Node and know how to pick the Key from multiple locations like the below , then it is scalable and works like the same way as built-in nodes

  • User Defined Property
  • LocalEnvironment
  • Environment
  • Any other valid location in the Message Assembly

Here is a solution which uses AES algorithm to encrypt and decrypt the messages. All you need is 16bytes KEY.

Test flow

The KEY can be hard coded or its location can be $LocalEnvironment/Destination/Encrypt/Key or any other path which can be defined here

Now, this makes flexible that the KEY can be inside the incoming message or from LocalEnvironment or from Environment tree too.

Let us see how the encrypted message looks like after passing a simple XML file like below

Test message
Debugger
After Encryption Node
Encrypted Message
Decrypted Message in OUT Queue

If you are looking for the same solution or would like to know our capabilities in IIB, please contact us at support@vaithu.com/WhatsApp +1 6123058684.

We’ve rich experience in IIB and executed multiple projects since 2013. So, we assure that you get your solution on time in low cost without compromising on quality and efficiency.

IBM Integration API – What shall I get from this?

  • Are you a serious IIB developer/admin?
  • Are you switching with multiple applications/windows back & forth?
  • Are you not a fan of commands ?

Yes. Yes. Yes. We were also looking for some sort of way to get most of our stuff done with some simple clicks/buttons. So, we started looking the ways to achieve it and finally found this IBM Integration API which contains everything you & we needed.

Let us put here some high level things that you can get from this API

  • List all
    • messages flows/applications/static/shared libraries
    • UDPs
    • Queues used
    • Security Identities used
    • DSNs
    • Bar files
    • Integration Server properties
    • Configurable Services
    • Activity Log
    • Administrative Log
    • SubFlows
  • Stop/Start
    • Message Flow
    • Application
    • Integration Server
  • Deploy/Undeploy bar files
  • Update/Modify/Create Configurable service
  • Update UDPs
  • Set Workload Management Properties

Most of the above features might be available from Web UI but it does contain have a way to search. Also, it does not allow to copy one bar file from one environment to another. But when you know the above stuffs to do programmatically, you can do what ever you need.

import com.ibm.broker.config.proxy.*;
public class DeployBAR {

  public static void main(String[] args) {
    BrokerConnectionParameters bcp =
       new MQBrokerConnectionParameters("localhost", 2414, "IB9QMGR");
    try {
      BrokerProxy b = BrokerProxy.getInstance(bcp);
      ExecutionGroupProxy eg = b.getExecutionGroupByName("default");
      DeployResult dr = eg.deploy("MyBAR.bar", true, 30000);
      System.out.println("Result = "+dr.getCompletionCode());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

You can copy everything from one server and put it in another server. You can cross verify what is in multiple environments and much more can be done easily.

If you want to know more about this, we take training on these periodically. Join one of our training and control the Node as you wish. For more details, contact us at support@vaithu.com/WhatsApp +1 6123058684.

MQEdit-Web-based RFHUtil

Are you using RFHUtil but looking for some alternatives for

  • Editing the message on the fly
  • PrettyPrint XML/JSON messages
  • List All queue details with human understandable format
  • Purge selective messages
  • Move messages from one queue manager to another
  • Move selective messages
  • Create Queue
  • Queue Properties
  • Search Queues
  • Read message from two different queue from the same window
  • Get description of the MQ Return Code
  • Trigger N messages at a time for load testing
  • And many more

Yes. We were also looking for the same and so built a tool to help you improve your productivity and lessen the development/testing time. This tool has most of the sought features available in RFHUtil. Here is the video demonstrating the features and how to use this tool.

This is tool is a web-based tool and so works on all platforms. All you need is to run the below command and open a browser,type localhost:8080

java -jar mqedit-1.0-SNAPSHOT.jar
Main Page

You can put all your queue manager configuration details like in a text file and put them in your user’s directory

IIBv10QMGR;LOCALHOST;1414;SYSTEM.DEF.SVRCONN

To purchase this software, please contact us at support@vaithu.com.

For immediate response, you can WhatsApp us at +1 6123058684.

Here is the POM file I use for my projects

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.vaithu.holon</groupId>
    <artifactId>holon-jdbc</artifactId>
    <name>Holon JDBC</name>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <vaadin.version>14.3.0</vaadin.version>
        <holon.platform.version>5.4.2</holon.platform.version>

    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
    </parent>

    <repositories>
        <!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->

        <!-- Main Maven repository -->
        <repository>
            <id>central</id>
            <url>https://repo1.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
        <!-- Repository used by many Vaadin add-ons -->
        <repository>
            <id>Vaadin Directory</id>
            <url>https://maven.vaadin.com/vaadin-addons</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <!-- Main Maven repository -->
        <pluginRepository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <version>${vaadin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.holon-platform</groupId>
                <artifactId>bom</artifactId>
                <version>${holon.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <!-- Replace artifactId with vaadin-core to use only free components -->
            <artifactId>vaadin</artifactId>
            <exclusions>
                <!-- Webjars are only needed when running in Vaadin 13 compatibility mode -->
                <exclusion>
                    <groupId>com.vaadin.webjar</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.insites</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.polymer</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.polymerelements</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.vaadin</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.webjars.bowergithub.webcomponents</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-spring-boot-starter</artifactId>
            <exclusions>
                <!-- Excluding so that webjars are not included. -->
                <exclusion>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-testbench</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- Holon: JDBC starter -->
        <dependency>
            <groupId>com.holon-platform.jdbc</groupId>
            <artifactId>holon-starter-jdbc-datastore-hikaricp</artifactId>
        </dependency>

        <!-- Holon: Vaadin Flow starter -->
        <dependency>
            <groupId>com.holon-platform.vaadin</groupId>
            <artifactId>holon-starter-vaadin-flow</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8 -->
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>19.7.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>spring-boot:run</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <!-- Clean build and startup time for Vaadin apps sometimes may exceed
                     the default Spring Boot's 30sec timeout.  -->
                <configuration>
                    <wait>500</wait>
                    <maxAttempts>240</maxAttempts>
                </configuration>
            </plugin>

            <!--
                Take care of synchronizing java dependencies and imports in
                package.json and main.js files.
                It also creates webpack.config.js if not exists yet.
            -->
            <plugin>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-maven-plugin</artifactId>
                <version>${vaadin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-frontend</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <!-- Production mode is activated using -Pproduction -->
            <id>production</id>
            <properties>
                <vaadin.productionMode>true</vaadin.productionMode>
            </properties>

            <dependencies>
                <dependency>
                    <groupId>com.vaadin</groupId>
                    <artifactId>flow-server-production-mode</artifactId>
                </dependency>
            </dependencies>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <configuration>
                            <jvmArguments>-Dvaadin.productionMode</jvmArguments>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <version>${vaadin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>build-frontend</goal>
                                </goals>
                                <phase>compile</phase>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>it</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>start-spring-boot</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>start</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>stop-spring-boot</id>
                                <phase>post-integration-test</phase>
                                <goals>
                                    <goal>stop</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>

                    <!-- Runs the integration tests (*IT) after the server is started -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <trimStackTrace>false</trimStackTrace>
                            <enableAssertions>true</enableAssertions>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

    </profiles>
</project>
SnackOrder example using Holon-Platform and Vaadin

SnackOrder example using Holon-Platform and Vaadin

This is my another post in learning my Vaadin journey through Holon Platform. There is already an example here https://vaadin.com/learn/tutorials/dynamic-web-forms-with-validation-in-java explaining the concepts but I just want to mimic the same so that I can learn more about the Holon Platform APIs myself.

Here is the simplified code for the Dynamic WebForm example of SnackOrder

import com.holonplatform.core.property.PropertyBox;
import com.holonplatform.vaadin.flow.components.Components;
import com.holonplatform.vaadin.flow.components.PropertyInputForm;
import com.holonplatform.vaadin.flow.components.PropertyListing;
import com.holonplatform.vaadin.flow.components.SingleSelect;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.router.Route;

import java.util.*;

@Route("Snack")
public class SnackOrderView extends VerticalLayout {

    private PropertyInputForm inputForm;
    private PropertyListing listing;

    public SnackOrderView() {

        initialize();


    }

    private void initialize() {

        Map<String, List<String>> snacks = new HashMap<>();
        snacks.put("Fruits", Arrays.asList("Banana", "Apple", "Orange", "Avocado"));
        snacks.put("Candy", Arrays.asList("Chocolate bar", "Gummy bears", "Granola bar"));
        snacks.put("Drinks", Arrays.asList("Soda", "Water", "Coffee", "Tea"));


        List<PropertyBox> snackOrders = new ArrayList<>();
        ListDataProvider<PropertyBox> gridDataProvider = new ListDataProvider<>(snackOrders);

        Button orderBtn = Components.button()
                .text("Order")
                .withThemeName("primary")
                .enabled(false)
                .onClick(event -> {
                    snackOrders.add(inputForm.getValue());
                    listing.refresh();
                })
                .build();

        SingleSelect<String> snackSelect = Components.input.singleSelect(String.class)
                .required()
                .enabled(false)
                .withValueChangeListener(event -> {
                    orderBtn.setEnabled(true);
                })
                .build();

        SingleSelect<String> snackTypeSelect = Components.input.singleSelect(String.class)
                .required()
                .items(snacks.keySet())
                .withValueChangeListener(event -> {
                    ((ComboBox<String>) snackSelect.getComponent()).setItems(snacks.get(event.getValue()));
                    ((ComboBox<String>) snackSelect.getComponent()).setEnabled(true);
                })
                .build();

        HorizontalLayout hl = Components.hl().build();

        inputForm = Components.input.form(hl, SnackOrder.PROPERTY_SET)
                .composer((content, source) -> {
                    source.getComponents().forEach(component -> {
                        content.add(component);
                    });
                    content.add(orderBtn);
                })
                .bind(SnackOrder.TYPE, snackTypeSelect)
                .bind(SnackOrder.SNACK, snackSelect)
                .initializer(content -> {
                    content.setSpacing(true);
                    content.setDefaultVerticalComponentAlignment(Alignment.BASELINE);
                })
                .withValueChangeListener(event -> {
                    orderBtn.setEnabled(inputForm.isValid());
                })
                .build();

        listing = Components.listing.properties(SnackOrder.PROPERTY_SET)
                .dataSource(gridDataProvider)
                .build();

        add(inputForm.getComponent(), listing.getComponent());

    }

}

Here is the screenprint showing the neat and simple web form

Vaadin Lazy Loading issues

I’ve a grid like this and if I edit the description column it throws error “java.lang.IndexOutOfBoundsException: Index: 0, Size: 0”.

It happens when there is only one matching value in the combobox filter. The combobox looks like this

The dataprovider used is

CallbackDataProvider<String, String> descDataProvider
                = DataProvider.fromFilteringCallbacks(query -> {
            String filter = query.getFilter().orElse("");
            datastore.query(Product.TARGET)
                    .restrict(query.getLimit(), query.getOffset())
                    .stream(Product.DESCRIPTION)
                    .filter(s -> StringUtils.startsWithIgnoreCase(s,filter))
                    .forEach(s -> System.out.print(s+"\t"));
            Stream<String> propertyBoxStream = datastore.query(Product.TARGET)
                    .restrict(query.getLimit(), query.getOffset())
                    .stream(Product.DESCRIPTION)
                    .filter(s -> StringUtils.startsWithIgnoreCase(s,filter));
                           // s -> s.startsWith(filter)
            return propertyBoxStream;
        }, query -> {
            String filter = query.getFilter().orElse("");
            long propertyBoxStream = datastore.query(Product.TARGET)
//                    .filter(Product.DESCRIPTION.startsWithIgnoreCase(filter))
//                    .filter(Product.DESCRIPTION.startsWithIgnoreCase(filter))
                    .stream(Product.DESCRIPTION)
            .filter(s -> StringUtils.startsWithIgnoreCase(s,filter))
                    .count();
            write("filter " + filter+"\t count :"+propertyBoxStream);
            return (int) propertyBoxStream;
        });

and the stacktrace is

java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
	at java.util.ArrayList.rangeCheck(ArrayList.java:653) ~[na:1.8.0_131]
	at java.util.ArrayList.get(ArrayList.java:429) ~[na:1.8.0_131]
	at com.vaadin.flow.data.provider.DataCommunicator.lambda$getJsonItems$3(DataCommunicator.java:615) ~[flow-data-2.2.2.jar:2.2.2]
	at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250) ~[na:1.8.0_131]
	at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110) ~[na:1.8.0_131]
	at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693) ~[na:1.8.0_131]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_131]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_131]
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_131]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_131]
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_131]
	at com.vaadin.flow.data.provider.DataCommunicator.getJsonItems(DataCommunicator.java:617) ~[flow-data-2.2.2.jar:2.2.2]
	at com.vaadin.flow.data.provider.DataCommunicator.collectChangesToSend(DataCommunicator.java:560) ~[flow-data-2.2.2.jar:2.2.2]
	at com.vaadin.flow.data.provider.DataCommunicator.flush(DataCommunicator.java:477) ~[flow-data-2.2.2.jar:2.2.2]
	at com.vaadin.flow.data.provider.DataCommunicator.lambda$requestFlush$2f364bb9$1(DataCommunicator.java:425) ~[flow-data-2.2.2.jar:2.2.2]
	at com.vaadin.flow.internal.StateTree.lambda$runExecutionsBeforeClientResponse$1(StateTree.java:368) ~[flow-server-2.2.2.jar:2.2.2]
	at java.util.ArrayList.forEach(ArrayList.java:1249) ~[na:1.8.0_131]
	at com.vaadin.flow.internal.StateTree.runExecutionsBeforeClientResponse(StateTree.java:365) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.communication.UidlWriter.encodeChanges(UidlWriter.java:411) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.communication.UidlWriter.createUidl(UidlWriter.java:187) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.communication.UidlRequestHandler.writeUidl(UidlRequestHandler.java:121) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1545) ~[flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) [flow-server-2.2.2.jar:2.2.2]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:120) [vaadin-spring-12.2.0.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-embed-websocket-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.27.jar:9.0.27]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]

I do not know what is the problem and why it fails when there is only one matching value. If you know any solution, please put in the comments below.