Buscar este blog

Theme images by MichaelJay. Powered by Blogger.

Datos personales

CSS Theming & Styling in Vaadin 14

Last week, the new LTS version of the presentation framework was announced. While you can find more information about the new features ...

Author Info

Video Of Day

Flickr

We deliver intelligence

Team of experts working to fulfill your software needs

About Us


Expertise

We are a team of professionals with extensive experience in the field of enterprise application development.

Our Services

We provide various services according to the needs of your business.

Efficiency

Trust in our knowledge, coding is our passion.

Contact

Feel free to contact, tell us your needs and we'll help you out.

Are you interested in what we do so far?
Let's talk about your project !

GET IN TOUCH

Flowing Blog
Explore our ideas

Thursday, August 22, 2019

CSS Theming & Styling in Vaadin 14

Last week, the new LTS version of the presentation framework was announced.
While you can find more information about the new features in the official site, I would like to focus on one specific feature that I’ve found interesting: styles management.
Across the years we saw different approaches in how to handle styles in Vaadin applications.
In Vaadin 6 you could just modify styles using plain CSS. Of course you had two choices: either build everything from scratch, or inherit the built-in themes like Reindeer, Runo or Chameleon. That inheritance scheme was based in the @import css statement, which is the basis of the cascading part of the theming technology.
The problem with this approach was that the customization was difficult, because the complexity of the rendered DOM, and the lack of variables that could help in modifying certain aspects of the base themes such as sizing and spacing, that several rules had in common.
Styling in Vaadin 6: Complex DOM Structure & lack of variables

That was one of the reasons that lead to changing the underlying theming technology in favor of SASS (which stands for "Syntactically Awesome Style Sheets") themes in Vaadin 7.
SASS is an extension of CSS that enables you to use variables, nested rules, inline imports and more. It also helps to keep things organised and allows you to create style sheets faster. It works by adding a post-processing step, that will render the whole SASS hierarchy in a single plain css final file.
With this power up in the themes architecture, Valo was born. It was a brand new theme with important customization features. You were able to change specific aspects with the use of SASS variables and rules, so the theme personalizations were significantly smaller, simpler and clearer.
Styling in Vaadin 7 & 8: SASS features
The downside was that making simple changes in the css, would mean to change scss files, and re-generate the final styles.css file on the fly, adding a small overhead to development cycle.

With the advent of Vaadin 10 and Web Components, everything changed. Now GWT was no longer responsible for rendering the client-side components, and the DOM structure was significantly simpler.
With the brand new, browser-supported, frontend technologies, the possibility of using new CSS 3 features was at hand. That meant that variables, clear inheritance and many other features could be used without a css post-processor engine.
Of course there are new big things to solve, like web component style encapsulation. Shadow DOM styling and more.
With this in mind, and the new Vaadin version based on these new technologies, the new theme Lumo appeared.
Lumo is an evolving design system foundation for modern web applications. It offers many customization paths, with the help of css variables.
Also later Material theme was released, with the same technical approach as Lumo.
Customizing them was just a matter of adding HTML files with a specific structure, that allowed the modification of not only global styles, but also styles that were to be injected into  specific components’ Shadow DOM.

Styling in Vaadin 10+: Web Components Theming

There were some caveats with this approach. As an example, the structure of these files was not so easy to remember, and existent tooling had to support this structure. Another problem was that you needed to import other style dependencies.
With the release of the new LTS version, a new feature was introduced: Simplified styling of application and components with @CssImport. This annotation removes the complexity of the previous version. Now you can easily import plain .css files directly into java code, without the need of post processing engines, while enjoying the new features of CSS3 & Web Components.

Styling in Vaadin 14+: @CssImport elegance

Some of the benefits of this approach:

  • The file reference is simpler
  • You can include multiple imports
  • The “themeFor” is specified in the annotation
  • No need to import dependencies in css
  • No more <custom-style>, <dom-module> or <template> tags

Now we should expect better looking Vaadin applications with simplified styling!

Wednesday, April 24, 2019

Lazy, Filtered and Sorted Vaadin Grid using External Data Source

In large enterprise application development projects, it's usual to code use cases that, as the main requirement, define to show the user huge amounts of data in a tabular way. For this kind of scenarios, there is a particular web component that comes really handy: a Grid. Given that we like Vaadin's framework, we are going to describe how to configure it in such a way that doesn't restrict you about performance issues when doing that. 
This post assumes that you have some knowledge of web application development using the Vaadin Framework and the Java Platform. But we’ll try to explain everything as much as possible. The version that we used to write this application is Vaadin 13, but this part of the API is almost the same since Vaadin 8, so it should be possible to use the same approach in older versions.
Setting up a Vaadin Grid, is really easy, just create an instance and then customize the columns, or even skip that part if your Pojo is sufficiently self-descriptive.
As an example, let’s assume that we want to show a grid with data for a person, which we can define as a simplified entity like this:

public class Person {



 private String name;

 private String lastName;

 private Integer age;

 

 public Person(String name, String lastName, Integer age) {

  super();

  this.name = name;

  this.lastName = lastName;

  this.age = age;

 }

 public String getName() {

  return name;

 }

 public void setName(String name) {

  this.name = name;

 }

 public String getLastName() {

  return lastName;

 }

 public void setLastName(String lastName) {

  this.lastName = lastName;

 }

 public Integer getAge() {

  return age;

 }

 public void setAge(Integer age) {

  this.age = age;

 }

}

And then we have a service that will have the responsibility of retrieving this information from a backend, like a database or a remote API. Let’s call it PersonService.
Suppose we want to show those entities in a Vaadin Grid, we would do this:


     List<Person> persons = getPersonService().fetchPersons();

     Grid<Person> personsGrid = new Grid<>(Person.class);

     personsGrid.setItems(persons);

This is fine for small amounts of data, but when dealing with large data sets some features, such as lazy loading, filtering and sorting, must be left to the backend, implementing that all at once can be a complex task, so let's review them.

Lazy Loading

First let’s define what we are talking about when we use this term. Usually when we are handling a list of items, we can choose to obtain  all of them, or just the ones that we want to display or handle in some way. Obviously it depends on the amount. If we are obtaining one hundred of them, it is something that we can manage directly in memory, but if we are handling millions, we have to deal with them in a different way.
This is the case when a mechanism such as lazy loading makes things easier.
Vaadin components, like Grid or ComboBox, already support this kind of behavior, without the need of doing something special, but it only will take care of retrieving what is needed in a lazy loading fashion between the web browser and your web application.
Given that Vaadin only takes care of the presentation layer of your application, you need to do something to apply this behavior from your underlying data source (database, REST API, etc.).


According to the official documentation, you need to ask to your backend two questions:
Can you tell me the total amount of items that we are dealing with?
Of those, can you only give me the first N items, skipping the previous M items?
You don’t need to calculate N and M, those numbers are provided by the framework. They are basically the limit (N) and offset (M). You answer those two questions by providing two lambda expressions to the method DataProvider.fromCallbacks(), something like this:


DataProvider<Person, Void> dataProvider = DataProvider.fromCallbacks(

        // First callback fetches items based on a query

        query -> {

            // The index of the first item to load

            int offset = query.getOffset();

            // The number of items to load

            int limit = query.getLimit();

            List<Person> persons = getPersonService()

                    .fetchPersons(offset, limit);

            return persons.stream();

        },

        // Second callback fetches the number of items for a query

        query -> getPersonService().getPersonCount());

);

Grid<Person> grid = new Grid<>();

grid.setDataProvider(dataProvider);

Now we added two new different methods to our service class.
But let’s continue with another relevant requirement.

Filtering

It’s a rather common request to narrow down the size of the queried items, and one typical way of doing that is to make grids filterable.
But before digging into this, we need to define what is a Filter. For us it’s just a class that will contain values that we want to be taken into account when deciding if a given item will be returned or not.
In our case, let’s assume that we only want to filter people by their name and last name:


public class PersonFilter {

 

 private String nameFilter = null;

 private String lastNameFilter = null;



 public PersonFilter() { 

 }

 

 public PersonFilter(String nameFilter, String lastNameFilter) {

  this.setNameFilter(nameFilter);

  this.setLastNameFilter(lastNameFilter);

 }



 public String getNameFilter() {

  return nameFilter;

 }



 public String getLastNameFilter() {

  return lastNameFilter;

 }



 public void setNameFilter(String nameFilter) {

  this.nameFilter = nameFilter;

 }



 public void setLastNameFilter(String lastNameFilter) {

  this.lastNameFilter = lastNameFilter;

 }

}

Now that we have our filter, how to do the actual filtering?
Instead of calling DataProvider.fromCallbacks(), we are going to use DataProvider.fromFilteringCallbacks(), makes sense, right?


        DataProvider<Person, PersonFilter> dataProvider =

            DataProvider.fromFilteringCallbacks(

            query -> {

              Optional<PersonFilter> filter = query.getFilter();

              return getPersonService().fetchPersons(

                query.getOffset(),

                query.getLimit(),

                filter.map(f -> f.getNameFilter()).orElse(null),

                filter.map(f -> f.getLastNameFilter()).orElse(null)

              );

            },

            query -> {

              Optional<PersonFilter> filter = query.getFilter();

              return getPersonService().getPersonCount(

                filter.map(f -> f.getNameFilter()).orElse(null),

                filter.map(f -> f.getLastNameFilter()).orElse(null)

              );

            }

          );

In this case, what we are doing, is just to obtain the filter from the query, and send the filter values to the backend class. We cannot do the filtering by ourselves because if the underlying backend is a database, then those filters have to be taken into account when building the SQL queries. If we do the filtering by ourselves, then it’s impossible to calculate the final count of the items, without retrieving all of the entities from the backend, causing our lazy loading mechanism to fail its goal (not to retrieve everything). The same applies when calling a remote API.
But let’s continue, if we want to change the filters dynamically, then we need to be able to configure the filters, for that we need to call the method withConfigurableFilter(), that will return an enhanced DataProvider with a method that will allow us to set a given Filter instance:


        PersonFilter gridFilter = new PersonFilter();

        ConfigurableFilterDataProvider<Person,Void,PersonFilter> dp = dataProvider.withConfigurableFilter();

        dp.setFilter(gridFilter);

We can change the filter later, or just save a reference to this instance and modify it’s values. After doing that a call to the method refreshAll() in the DataProvider will trigger the loading of the data with the new filter values.
Now, what about the visual part? … let’s see:

        HeaderRow hr = personsGrid.prependHeaderRow();

        TextField nameFilterTF = new TextField();

        nameFilterTF.addValueChangeListener(ev->{

         gridFilter.setNameFilter(ev.getValue());

         dp.refreshAll();

        });

        hr.getCell(personsGrid.getColumnByKey("name")).setComponent(nameFilterTF);

        TextField lastNameFilterTF = new TextField();

        lastNameFilterTF.addValueChangeListener(ev->{

         gridFilter.setLastNameFilter(ev.getValue());

         dp.refreshAll();

        });

        hr.getCell(personsGrid.getColumnByKey("lastName")).setComponent(lastNameFilterTF);     

First we are creating a HeaderRow, that is a row that will show at the top of our fancy grid, that will contain components that will filter our data.
Then we are creating a TextField for holding the strings to filter the name and last name of our people.
Finally we are adding some value change listeners that will actually apply the filters when changing the value.
That’s great! … now we are loading filtered data in a lazy way using multiple filters.
But what if we need to sort the data? … let’s continue.

Sorting

Similarly to our filtering case, we need a class to store each sorting information that we need:


public class PersonSort {



 private String propertyName;

 private boolean descending;

 

 public String getPropertyName() {

  return propertyName;

 }

 public void setPropertyName(String propertyName) {

  this.propertyName = propertyName;

 }

 public boolean isDescending() {

  return descending;

 }

 public void setDescending(boolean descending) {

  this.descending = descending;

 }

  

}

The class is pretty self-explained. Just holding the property that is currently being sorted, and a boolean for specifying if we sort up or down.
You might think why we are constructing these classes (PersonFilter and PersonSort), given that we could just pass the values directly to the service. The main reason is to have framework agnostic classes to hold these kind of information and then pass them to the backend, making a cleaner separation of layers.
In our example, we are going to provide a new parameter to our PersonService: a list of PersonSort (sort orders). This is a list, because the order of the sort criteria is important, you can establish this order in the Grid component, by calling personsGrid.setMultiSort(true). Let’s review the changes in our code:


        DataProvider<Person, PersonFilter> dataProvider =

          DataProvider.fromFilteringCallbacks(

          query -> {

            Optional<PersonFilter> filter = query.getFilter();

            List<PersonSort> sortOrders = query.getSortOrders().stream().map(sortOrder->new PersonSort(sortOrder.getSorted(),sortOrder.getDirection().equals(SortDirection.ASCENDING))).collect(Collectors.toList());

            return getPersonService().fetchPersons(

              query.getOffset(),

              query.getLimit(),

              filter.map(f -> f.getNameFilter()).orElse(null),

              filter.map(f -> f.getLastNameFilter()).orElse(null),

              sortOrders

            );

          },

          query -> {

            Optional<PersonFilter> filter = query.getFilter();

            return getPersonService().getPersonCount(

              filter.map(f -> f.getNameFilter()).orElse(null),

              filter.map(f -> f.getLastNameFilter()).orElse(null)

            );

          }

        );

Now we are assembling this list of PersonSort, using query.getSortOrders().
The implementation of PersonService is irrelevant, because it's up to the backend to provide the data requested using the information provided:

  • Lazy loading information: offset and limit
  • Filtering information: name and last name filters
  • Sorting information: list of PersonSort

If the backend obtains the data from a relational database, then a SQL clause has to be created dynamically based on that information. For example:


SELECT *

FROM PERSONS P

WHERE P.NAME LIKE %FILTERNAME% AND P.LASTNAME LIKE %LASTNAME%

ORDER BY P.NAME DESC, P.LASTNAME ASC

LIMIT OFFSET,LIMIT

Here's a small animation showing our grid in action:


You can play around with this example, by checking this GitHub project with the sources.
Have fun!

Wednesday, April 3, 2019

Our 2nd year in review: keep flowing!

Another round around the sun, another term ended, and here we are still moving on. A lot of things happened since this team was created, and many of them last year. Here’s a quick review of what we did:

Traveling

Let’s start with one of the best experiences we got the chance to share as a team. We had the opportunity to visit the northern hemisphere to meet our friends at Vaadin’s main HQ.
While we were there, we shoot some awesome pictures, visit some interesting places and had the amazing chance of getting to know all of the experts behind the company that is responsible for this great open source framework.

Sharing

Talking about Open Source, we continued to support our community, and created a special section in our web site to group all of the projects that we maintain.
We worked hard to develop a bunch of interesting projects, giving away our best effort to make them production ready, so anyone can use our technologies in their projects, and participate with us actively so they can improve over time.
One interesting project to mention, was a small PWA application that displayed the results of the Football Worldcup in real time, showing how to integrate several technologies, so similar projects can be built using this a kickstart.

Learning

Delivering intelligence is not an easy task if you don’t find a way to expand your knowledge. We take this statement seriously: we schedule one learning day each week, so we can watch, learn and discuss about many technologies, methodologies, frameworks, languages, etc.
Here’s a list of the subjects and some interesting links for you to watch if you’re curious:


Writing

Having the opportunity to learn, and code, one final step is to share some of this knowledge, so we wrote some interesting articles about specific subjects, here’s a short list:


Speaking

But that is not all. We organized a talk in one of the most important universities in the area: Universidad Nacional del Litoral.
The chosen topic was to explain what is all the fuzz about Vaadin 10 and Web components.
You can find more information about it in our blog.

Delivering

We finished some interesting projects for new customers, growing our portfolio. Here is a summary of them, but with the promise that we will expand these experiences later in our site:

  • We continue working as consultants for big medical software implementations in U.S., and also giving technical and architectural support for big companies all around the globe.
  • Full SCM implementation for a customer in Colombia, that involved the installation and configuration of several servers, testing the entire stack, training several areas and finally taking care of every detail while going to production
  • Development support for a big application related to job openings, of a customer from Buenos Aires, that involved working with email marketing campaign tools and invocation of REST-APIs
  • Vaadin 7 to 13 migration, of a web module of an ERP software of a company from Rosario - Argentina

Networking

We continued sharing everything in our social networks, now you can find us in:


So that’s it, we are really happy with our results, so let’s finish with this quote from Albert Einstein:

Life is like riding a bicycle. To keep your balance you must keep moving.

In our case we will keep flowing. Thanks for reading!

Tuesday, January 8, 2019

Creating a Vaadin Flow Server-Side API for a Javascript component

Today we are going to explore some tips about how to create a Java server-side wrapper for a regular javascript component using Vaadin Flow. As you might notice, this popular framework has good documentation about how to integrate an existing Polymer Component, but there is no much info about how to integrate a regular Javascript component, so we will show you one easy approach of doing that.
What we want to do is, to show you how to create a nice Java API around a typical javascript component, so you can easily integrate it in your java applications.
Of course, there are many ways to build javascript visual components around there, we will focus on the ones that use this common pattern: you create a html element (like a Div), and then you instruct the library to "enhance" it.
Then we have one important feature that is usually wanted: bidirectional communication between the server and the client.
For this short tutorial we want to build a Vaadin Flow wrapper around one interesting library that is able to draw time line graphs: vis.js. This library is based on the previous premise: to enhance (in this case) a div html tag.
Let's start.

Step 1: Overview of your component

First, it’s a good idea to use a starter to build a project based on Vaadin. We will use this one, which is perfect for creating a new component. Because it’s mandatory to specify a base GitHub project, just leave the one that is offered, you can change that later.
We want our component to be easy to use; hence, following Vaadin conventions, we will create a simple class that will extend a Div component. This class will be able to render the component in the client side, exposing some methods that will give the developer the ability for interacting with it in several ways:

public class Timeline extends Div {

}

Step 2: Defining dependencies

If we were going to use the component in a regular web page, the first thing that we would need to do is to tell the browser to fetch the libraries and styles, and the same holds true for a Vaadin Application.
You have three ways to do this:
  • Download the library and just copy the static resources in your src/main/resources/META-INF/resources directory, and they will be served in your web application.
  • Use a CDN
  • Use a webjar dependency
The first option is stable enough, but it could bring problems if you forget to unzip something (additionally version management is a bit cumbersome). The second one is a good choice, but you can’t always find out there the library that you want to use. Another drawback is that users with restricted access to the internet will not be able to use your component.
So we will use the webjar dependency strategy. For a detailed explanation, we recommend you to read this article.
In our case, this step involves basically adding the following to your pom file:

<dependency>
 <groupId>org.webjars.npm</groupId>
 <artifactId>vis</artifactId>
 <version>4.21.0</version>
</dependency>

But how  to tell the browser to only import the library and styles when the component is needed? In Vaadin Flow that is easy, just use a couple of annotations in your component:

@JavaScript("/webjars/vis/4.21.0/dist/vis.js")
@StyleSheet("/webjars/vis/4.21.0/dist/vis-timeline-graph2d.min.css")
public class Timeline extends Div {

}

Step 3: Creating the component instance

According to the vis.js documentation, you need to do three things to give life to our component:

  1. Find the div that will host the visual component
  2. Create some configuration data
  3. Create the TimeLine

This is done by this plain javascript snippet:

// DOM element where the Timeline will be attached
var container = document.getElementById('visualization');

// Create a DataSet (allows two way data-binding)
var items = new vis.DataSet([
  {id: 1, content: 'item 1', start: '2013-04-20'},
  {id: 2, content: 'item 2', start: '2013-04-14'},
  {id: 3, content: 'item 3', start: '2013-04-18'},
  {id: 4, content: 'item 4', start: '2013-04-16', end: '2013-04-19'},
  {id: 5, content: 'item 5', start: '2013-04-25'},
  {id: 6, content: 'item 6', start: '2013-04-27'}
]);

// Configuration for the Timeline
var options = {};

// Create a Timeline
var timeline = new vis.Timeline(container, items, options);        

There are several ways of calling this from our component, we will use the executeJavaScript() method of the useful Page Vaadin object.
For that we will create a String that will contain this javascript function, with only some modifications. First, we will provide the container as a parameter. The container is basically our Div class (TimeLine). We can send it as a parameter and then reference it inside the function using the “$0” placeholder. We could send more parameters by using “$1”,”$2” and so on.
Now we need to send the Items, for that we need to create a class for those:

public class Item {
 
 private Integer id;
 private LocalDate start;
 private LocalDate end;
 private String content;
 public Item(Integer id, LocalDate start, LocalDate end, String content) {
  super();
  this.id = id;
  this.start = start;
  this.end = end;
  this.content = content;
 }

  /* getters and setters */

 protected String toJSON() {
  JsonObject js = Json.createObject();
  if (getId()!=null) js.put("id", getId());
  if (getContent()!=null) js.put("content", getContent());
  if (getStart()!=null) js.put("start", getStart().toString());
  if (getEnd()!=null) js.put("end", getEnd().toString());
  
  return js.toJson();
 }

}

To generate the function we are going to use to initiate the library, we will use this method:

private String createInitFunction() {
 String function = "  // Create a DataSet (allows two way data-binding)\n" + 
   "  var items = new vis.DataSet([\n" + 
   items.stream().map(item->item.toJSON()).collect(Collectors.joining(",")) +
   "  ]);\n" + 
   "\n" + 
   "  // Configuration for the Timeline\n" + 
   "  var options = {};\n" + 
   "\n" + 
   "  // Create a Timeline\n" + 
   "  var timeline = new vis.Timeline($0, items, options);" + 
   "  $0.timeline = timeline";
 return function;
}

We will explain the line “$0.timeline = timeline” later.
Finally, we need to invoke this initialization function from the constructor, which will receive a list of items:

public Timeline(Item ... items) {
 this.items = Arrays.asList(items);
 String initFunction = createInitFunction();
 UI.getCurrent().getPage().executeJavaScript(initFunction , this); 
}

We can now test our component. With just this little line in the DemoView we can run the application and have an early look of it running in our browser:

@Route("")
public class DemoView extends Div {
    public DemoView() {
        add(new Timeline(new Item(1,LocalDate.now(), LocalDate.now().plusDays(2), "Task 1")));
    }   
}

Step 4: Client-Server communication

First, let’s see how to invoke a given method of our javascript component from the server side.
Suppose we want to invoke the method focus() of the timeline javascript component. The catch in here is that we need a reference to the timeline object created by the initialization method. That was accomplished with the line $0.timeline = timeline on the initialization function, we basically stored a reference to it in our div element.
Then we can invoke a method by using:

public void focus(Item item) {
 UI.getCurrent().getPage().executeJavaScript("$0.timeline.focus($1)", this,item.getId());
}

In this method we receive a given item and send the id as a parameter to the method focus, as specified by the public API of the timeline.
Now the other way around: our javascript component will produce events that we want to catch from the server side. How to do that? By creating a custom Event. In our case, we want to be able to do something when a given item is clicked; thus, we need to define the ItemClickEvent:

@DomEvent("click")
static public class ItemClickEvent extends ComponentEvent<Timeline> {
 
 private Item item;
 
  public ItemClickEvent(Timeline source, boolean fromClient,
   @EventData("element.timeline.getEventProperties(event).item") int id) {
  super(source, fromClient);
  source.items.stream().filter(item -> item.getId().equals(id)).findFirst()
    .ifPresent(founditem -> this.item = founditem);
 }

  public Item getItem() {
  return item;
 }
}

Lot of things to say for this code:
With @DomEvent(“click”) we are telling flow that we want to listen for “click” events fired in the client side
We are extending ComponentEvent<Timeline>. That will give us some basic stuff like for example the ability of unregistering the listener
With @EventData, we are informing that we want to bring some data along the event. Basically we are calling the method getEventProperties(event) of the stored timeline instance, and then retrieving the item that was clicked. The item is offered by a integer, which we will use to obtain the correspondent Item java instance in the server side.
Ok, now we have the event, but we need to offer the API for registering a listener that will receive our event:

public Registration addItemClickListener(ComponentEventListener<ItemClickEvent> listener) {
 return addListener(ItemClickEvent.class, listener);
}

As you can see, our method will receive a ComponentEventListener based on our ItemClickEvent, and with that it will call the inherited method addListener() that will take care of the necessary tasks for making it work.

Step 5: Use it and have fun!

Using our component is as simple as this:

Timeline tl = new Timeline(new Item(1,LocalDate.now(), LocalDate.now().plusDays(2), "Task 1"));

We can also do something when a given item is clicked:

tl.addItemClickListener(ev->Notification.show("Clicked on item: " + ev.getItem().getContent()));

Finally we can focus on a task:


Button b1 = new Button("Focus task 1");
b1.addClickListener(ev->tl.focus(items[0]));

And that’s it!
Here's an animated GIF that shows the main features of this tutorial:


If you want to play around, the sources are available in GitHub. The example is structured as a sequence of steps, where each commit represents an incremental change from the Add-on Component Starter for Flow
We are planning to release a component based on this example, stay tuned!

Our Services


Development
Enterprise Application Level

Java development for your company's needs.

Outsourcing and Projects Get in touch
Consulting
Architectural and Design support

Team of high qualified engineers will help you build your software infrastructure.

Outsourcing and Projects Get in touch
SCM
Build pipeline definition

We'll help you define how your build your software in an industrial level.

Consulting Get in touch
Open Source
Community driven development

Checkout our projects at GitHub. Be part of our community.

Contribute Get in touch

Contact Us


Flowing Code S.A.
San Martín 3472 - Oficina Sur - Santa Fe
Santa Fe, Argentina
+54 342 4123621
contact@flowingcode.com



Interested for our works and services?
Get more of our update !