Posted on Leave a comment

Improvements in .NET Core 3.0 for troubleshooting and monitoring distributed apps

Avatar

Sourabh

Post was authored by Sergey Kanzhelev. Thank you David Fowler and Richard Lander for reviews.

Introduction

Operating distributed apps is hard. Distributed apps typically consists of multiple components. These components may be owned and operated by different teams. Every interaction with an app results in distributed trace of code executions across many components. If your customer experiences a problem – pinpointing the root cause in one of components participated in a distributed trace is a hard task.

One big difference of distributed apps comparing to monoliths is a difficulty to correlate telemetry (like logs) across a single distributed trace. Looking at logs you can see how each component processed each request. But it is hard to know which request in once component and request in other component belong to the same distributed trace.

Historically, Application Performance Monitoring (APM) vendors provided the functionality of distributed trace context propagation from one component to another. Telemetry is correlated using this context. Due to heterogeneous nature of many environments, with components owned by different teams and using different tools for monitoring, it was always hard to instrument distributed apps consistently. APM vendors provided automatic code injection agents and SDKs to handle complexity of understanding various distributed context formats and RPC protocols.

With the upcoming transition of W3C Trace Context specification into Proposed Recommendation maturity level, and support of this specification by many vendors and platforms, the complexity of the context propagation is decreasing. The W3C Trace Context specification describes semantics of the distributed trace context and its format. This ensures that every component in a distributed app may understand this context and propagate it to components it calls into.

Microsoft is working on making distributed apps development easier with many ongoing developments like Orleans framework and project Dapr. As for distributed trace context propagation – Microsoft services and platforms will be adopting a W3C Trace Context format.

We believe that ASP.NET Core must provide an outstanding experience for building distributed tracing apps. With every release of ASP.NET Core we execute on this promise. This post describes the scenario of distributed tracing and logging highlighting improvements in .NET Core 3.0 and talks about discussions of a new exciting features we plan to add going forward.

Distributed Tracing and Logging

Let’s explore distributed tracing in .NET Core 3.0 and improvements recently made. First, we’ll see how two “out of the box” ASP.NET Core 3.0 apps has logs correlated across the entire distributed trace. Second, we’ll explore how easy it is to set distributed trace context for any .NET Core application and how it will automatically be propagated across http. And third, we’ll see how the same distributed trace identity is used by telemetry SDKs like OpenTelemetry and ASP.NET Core logs.

This demo will also demonstrate how .NET Core 3.0 embraces W3C Trace Context standard and what other features it offers.

Demo set up

In this demo we will have three simple components: ClientApp, FrontEndApp and BackEndApp.

BackEndApp is a template ASP.NET Core application called WeatherApp. It exposes a REST API to get a weather forecast.

FrontEndApp proxies all incoming requests into the calls to BackEndApp using this controller:

[ApiController]
[Route("[controller]")]
public class WeatherForecastProxyController : ControllerBase
{ private readonly ILogger<WeatherForecastProxyController> _logger; private readonly HttpClient _httpClient; public WeatherForecastProxyController( ILogger<WeatherForecastProxyController> logger, HttpClient httpClient) { _logger = logger; _httpClient = httpClient; } [HttpGet] public async Task<IEnumerable<WeatherForecast>> Get() { var jsonStream = await _httpClient.GetStreamAsync("http://localhost:5001/weatherforecast"); var weatherForecast = await JsonSerializer.DeserializeAsync<IEnumerable<WeatherForecast>>(jsonStream); return weatherForecast; }
}

Finally, ClientApp is a .NET Core 3.0 Windows Forms app. ClientApp calls into FrontEndApp for the weather forecast.

private async Task<string> GetWeatherForecast()
{ return await _httpClient.GetStringAsync( "http://localhost:5000/weatherforecastproxy");
}

Please note, there were no additional SDKs enabled or libraries installed on demo apps. As the demo progresses – every code change will be mentioned.

Correlated logs

Let’s make the very first call from ClientApp and take a look at the logs produced by FrontEndApp and BackEndApp.

FrontEndApp (a few line breaks added for readability):

info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] => ConnectionId:0HLR1BR0PL1CH => RequestPath:/weatherforecastproxy RequestId:0HLR1BR0PL1CH:00000001, SpanId:|363a800a-4cf070ad93fe3bd8., TraceId:363a800a-4cf070ad93fe3bd8, ParentId:
Executed endpoint 'FrontEndApp.Controllers.WeatherForecastProxyController.Get (FrontEndApp)'

BackEndApp:

info: BackEndApp.Controllers.WeatherForecastController[0] => ConnectionId:0HLR1BMQHFKRL => RequestPath:/weatherforecast RequestId:0HLR1BMQHFKRL:00000002, SpanId:|363a800a-4cf070ad93fe3bd8.94c1cdba_, TraceId:363a800a-4cf070ad93fe3bd8, ParentId:|363a800a-4cf070ad93fe3bd8. Executed endpoint 'FrontEndApp.Controllers.WeatherForecastController.Get (BackEndApp)'

Like magic, logs from two independent apps share the same TraceId. Behind the scene, ASP.NET Core 3.0 app will initialize a distributed trace context and pass it in the header. This is how incoming headers to the BackEndApp looks like:

You may notice that FrontEndApp didn’t receive any additional headers:

The reason is that in ASP.NET Core apps – distributed trace being initiated by ASP.NET Core framework itself on every incoming request. Next section explains how to do it for any .NET Core 3.0 app.

Initiate distributed trace in .NET Core 3.0 app

You may have noticed the difference in behavior of Windows Forms ClientApp and ASP.NET Core FrontEndApp. ClientApp didn’t set any distributed trace context. So FrontEndApp didn’t receive it. It is easy to set up distributed operation. Easiest way to do it is to use an API called Activity from the DiagnosticSource package.

private async Task<string> GetWeatherForecast()
{ var activity = new Activity("CallToBackend").Start(); try { return await _httpClient.GetStringAsync( "http://localhost:5000/weatherforecastproxy"); } finally { activity.Stop(); }
}

Once you have started an activity, HttpClient knows that distributed trace context needs to be propagated. Now all three components – ClientApp, FrontEndApp and BackEndApp share the same TraceId.

W3C Trace Context support

You may notice that the context is propagating using the header called Request-Id. This header was introduced in Asp.Net Core 2.0 and is used by default for better compatibility with these apps. However, as the W3C Trace Context specification is being widely adopted, it is recommended to switch to this format of context propagation.

With .NET Core 3.0, it is easy to switch to W3C Trace Context format to propagate distributed trace identifiers. Easiest way to do it is in the main method- just add a simple line in the Main method:

static void Main()
{ Activity.DefaultIdFormat = ActivityIdFormat.W3C; … Application.Run(new MainForm());
}

Now, when the FrontEndApp receives requests from the ClientApp, you see a traceparent header in the request:

The ASP.NET Core app will understand this header and recognize that it needs to use W3C Trace Context format for outgoing calls now.

Note, ASP.NET Core apps will recognize the correct format of distributed trace context automatically. However, it is still a good practice to switch the default format of distributed trace context to W3C for better interoperability in heterogeneous environments.

You will see all the logs attributed with the TraceId and SpanId obtained from the incoming header:

info: Microsoft.AspNetCore.Hosting.Diagnostics[1] => ConnectionId:0HLQV2BC3VP2T => RequestPath:/weatherforecast RequestId:0HLQV2BC3VP2T:00000001, SpanId:da13aa3c6fd9c146, TraceId:f11a03e3f078414fa7c0a0ce568c8b5c, ParentId:5076c17d0a604244 Request starting HTTP/1.1 GET http://localhost:5000/weatherforecast

Activity and distributed tracing with OpenTelemetry

OpenTelemetry provides a single set of APIs, libraries, agents, and collector services to capture distributed traces and metrics from your application. You can analyze them using Prometheus, Jaeger, Zipkin, and other observability tools.

Let’s enable OpenTelemetry on the BackEndApp. It is very easy to do, just call AddOpenTelemetry on startup:

services.AddOpenTelemetry(b => b.UseZipkin(o => { o.ServiceName="BackEndApp"; o.Endpoint=new Uri("http://zipkin /api/v2/spans"); }) .AddRequestCollector());

Now, as we just saw, TraceId in the FrontEndApp logs will match TraceId in the BackEndApp.

info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] => ConnectionId:0HLR2RC6BIIVO => RequestPath:/weatherforecastproxy RequestId:0HLR2RC6BIIVO:00000001, SpanId:54e2de7b9428e940, TraceId:e1a9b61ec50c954d852f645262c7b31a, ParentId:69dce1f155911a45 => FrontEndApp.Controllers.WeatherForecastProxyController.Get (FrontEndApp)
Executed action FrontEndApp.Controllers.WeatherForecastProxyController.Get (FrontEndApp) in 3187.3112ms info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] => ConnectionId:0HLR2RLEHSKBV => RequestPath:/weatherforecast RequestId:0HLR2RLEHSKBV:00000001, SpanId:0e783a0867544240, TraceId:e1a9b61ec50c954d852f645262c7b31a, ParentId:54e2de7b9428e940 => BackEndApp.Controllers.WeatherForecastController.Get (BackEndApp)
Executed action BackEndApp.Controllers.WeatherForecastController.Get (BackEndApp) in 3085.9111ms

Furthermore, the same Trace will be reported by Zipkin. So now you can correlate distributed traces collected by your distributed tracing tool and logs from the machine. You can also give this TraceId to the user when ClientApp experience issues. The user can share it with your app support and corresponding logs and distributed traces can be easily discovered across all components.

Taking example one step further – you can easily enable monitoring for all three components and see them on the gantt chart.

ASP.NET Core apps integrates with distributed trace

As we just seen telemetry collected by Application Monitoring vendors is correlated using the same distributed trace context as ASP.NET Core uses. This makes ASP.NET Core 3.0 apps great for the environments where different components are owned by different teams.

Imagine that only two of apps – A and C on the picture below enabled telemetry collection using SDK like OpenTelemetry. Before ASP.NET Core 3.0 it would mean that distributed tracing will not work, and a trace will be “broken” by app B.

With ASP.NET Core 3.0, since in most deployments ASP.NET Core apps are configured with the basic logging enabled, app B will propagate distributed trace context. This distributed traces from A and C will be correlated.

With the example of apps from before – if ClientApp and BackEndApp are instrumented and FrontEndApp is not – you see distributed trace is still being correlated:

This also makes ASP.NET Core apps great for the service mesh environments. In service mesh deployments, A and C from the picture above may represent a service mesh. In order for service mesh to stitch request entering and leaving component B – certain headers have to be propagated by an app. See this note from the Istio for example:

Although Istio proxies are able to automatically send spans, they need some hints to tie together the entire trace. Applications need to propagate the appropriate HTTP headers so that when the proxies send span information, the spans can be correlated correctly into a single trace.

As we work with service mesh authors to adopt W3C Trace Context format, ASP.NET Core apps will “just work” and propagate needed headers.

Passing additional context

Talking about other scenarios, it is often the case that you want to share more context between components in a distributed app. Let’s say a ClientApp wants to send its version so all REST calls will know where the request is coming from. You can add these properties in Activity.Baggage like this:

private async Task<string> GetWeatherForecast()
{ var activity = new Activity("CallToBackend") .AddBaggage("appVersion", "v1.0") .Start(); try { return await _httpClient.GetStringAsync( "http://localhost:5000/weatherforecastproxy"); } finally { activity.Stop(); }
}

Now on server side you see an additional header Correlation-Context in both – FrontEndApp and BackEndApp.

And you can use the Activity.Baggage to attribute your logs:

var appVersion = Activity.Current.Baggage.FirstOrDefault(b => b.Key == "appVersion").Value;
using (_logger.BeginScope($"appVersion={appVersion}"))
{ _logger.LogInformation("this weather forecast is from random source");
}

And you see the scope now contains an appVersion:

info: FrontEndApp.Controllers.WeatherForecastController[0] => ConnectionId:0HLQV353507UG => RequestPath:/weatherforecast RequestId:0HLQV353507UG:00000001, SpanId:37a0f7ebf3ecac42, TraceId:c7e07b7719a7a3489617663753f985e4, ParentId:f5df77ba38504846 => FrontEndApp.Controllers.WeatherForecastController.Get (BackEndApp) => appVersion=v1.0 this weather forecast is from random source

Next steps

With the improvements for ASP.NET Core 3.0 we hear that some of the features included in ASP.NET Core is hard to consume. Developers and DevOps wants a turnkey telemetry solution that will work with many APM vendors. We believe that investments we are making in OpenTelemetry will allow more people to benefit from investments we are making in ASP.NET Core monitoring and troubleshooting. This is one of the big areas of investments for a team.

We also help people adopt W3C Trace Context everywhere and will be making it a default distributed trace context propagation format in future versions of ASP.NET Core.

Another area of investments is to improve distributed context propagation scenarios. Distributed apps comparing to monoliths are lacking common shared state with the lifetime of a single distributed trace. This shared state (or context) can be used for basic logging as was described in this article, as well as for advanced routing of requests, experimentation, A/B testing, business context propagation, etc. Some of scenarios are described in this epic: Distributed Context in ASP.NET and Open Telemetry.

Please send us your feedback and tell what improvements in distributed apps troubleshooting and monitoring we need to make.

Avatar

Posted on Leave a comment

New features in Red Hat CodeReady Studio 12.13.0.GA and JBoss Tools 4.13.0.Final for Eclipse 2019-09

JBoss Tools 4.13.0 and Red Hat CodeReady Studio 12.13 for Eclipse 2019-09 are here and waiting for you. In this article, I’ll cover the highlights of the new releases and show how to get started.

Installation

Red Hat CodeReady Studio (previously known as Red Hat Developer Studio) comes with everything pre-bundled in its installer. Simply download it from our Red Hat CodeReady Studio product page and run it like this:

java -jar codereadystudio-<installername>.jar

JBoss Tools or Bring-Your-Own-Eclipse (BYOE) CodeReady Studio requires a bit more.

This release requires at least Eclipse 4.13 (2019-09), but we recommend using the latest Eclipse 4.13 2019-09 JEE Bundle because then you get most of the dependencies pre-installed.

Once you have installed Eclipse, you can either find us on the Eclipse Marketplace under “JBoss Tools” or “Red Hat CodeReady Studio.”

For JBoss Tools, you can also use our update site directly:

http://download.jboss.org/jbosstools/photon/stable/updates/

What’s new?

Our main focus for this release was improvements for container-based development and bug fixing. Eclipse 2019-06 itself has a lot of new cool stuff, but I’ll highlight just a few updates in both Eclipse 2019-06 and JBoss Tools plugins that I think are worth mentioning.

Red Hat OpenShift

OpenShift Container Platform 4.2 support

With the new OpenShift Container Platform (OCP) 4.2 now available (see the announcement), even if this is a major shift compared to OCP 3, Red Hat CodeReady Studio and JBoss Tools are compatible with this major release in a transparent way. Just define your connection to your OCP 4.2 based cluster as you did before for an OCP 3 cluster, and use the tooling!

CodeReady Containers 1.0 Server Adapter

A new server adapter has been added to support the next generation of CodeReady Containers 1.0. Although the server adapter itself has limited functionality, it is able to start and stop the CodeReady Containers virtual machine via its crc binary. Simply hit Ctrl+3 (Cmd+3 on OSX) and type new server, which will bring up a command to set up a new server.

crc server adapter

Enter crc in the filter textbox.

You should see the Red Hat CodeReady Containers 1.0 server adapter.

Select Red Hat CodeReady Containers 1.0 and click Next.

All you have to do is set the location of the CodeReady Containers crc binary file and the pull secret file location, which can be downloaded from https://cloud.redhat.com/openshift/install/crc/installer-provisioned.

Once you’re finished, a new CodeReady Containers server adapter will then be created and visible in the Servers view.

Once the server is started, a new OpenShift connection should appear in the OpenShift Explorer view, allowing the user to quickly create a new Openshift application and begin developing their AwesomeApp in a highly replicatable environment.

Server tools

Wildfly 18 Server Adapter

A server adapter has been added to work with Wildfly 18. It adds support for Java EE 8 and Jakarta EE 8.

EAP 7.3 Beta Server Adapter

A server adapter has been added to work with EAP 7.3 Beta.

Hibernate Tools

Hibernate Runtime Provider Updates

A number of additions and updates have been performed on the available Hibernate runtime providers.

The Hibernate 5.4 runtime provider now incorporates Hibernate Core version 5.4.7.Final and Hibernate Tools version 5.4.7.Final.

The Hibernate 5.3 runtime provider now incorporates Hibernate Core version 5.3.13.Final and Hibernate Tools version 5.3.13.Final.

Platform

Views, Dialogs and Toolbar

The new Quick Search dialog provides a convenient, simple and fast way to run a textual search across your workspace and jump to matches in your code. The dialog provides a quick overview showing matching lines of text at a glance. It updates as quickly as you can type and allows for quick navigation using only the keyboard. A typical workflow starts by pressing the keyboard shortcut Ctrl+Alt+Shift+L (or Cmd+Alt+Shift+L on Mac). Typing a few letters updates the search result as you type. Use Up-Down arrow keys to select a match, then hit Enter to open it in an editor.

Save editor when Project Explorer has focus

You can now save the active editor even when the Project Explorer has focus. In cases where an extension contributes Saveables to the Project Explorer, the extension is honored and the save action on the Project Explorer will save the provided saveable item instead of the active editor.

“Show In” context menu available for normal resources

The Show In context menu is now available for an element inside a resource project on the Project Explorer.

Show colors for additions and deletions in Compare viewer

In simple cases such as a two-way comparison or a three-way comparison with no merges and conflicts, the Compare viewer now shows different colors, depending on whether text has been added, removed, or modified. The default colors are green, red, and black, respectively.

The colors can be customized through usual theme customization approaches, including using related entries in the Colors and Fonts preference page.

Editor status line shows more selection details

The status line for Text Editors now shows the cursor position, and when the editor has something selected, it shows the number of characters in the selection as well. This also works in the block selection mode.

These two new additions to the status line can be disabled via the General > Editors > Text Editors preference page.

Shorter dialog text

Several dialog texts have been shortened. This allows you to capture important information faster.

Previously:

Now:

Close project via middle-click

In the Project Explorer, you can now close a project using middle-click.

Debug

Improved usability of Environment tab in Launch Configurations

In the Environment tab of the Launch Configuration dialog, you can now double-click on an environment variable name or value and start editing it directly from the table.

Right-clicking on the environment variable table now opens a context menu, allowing for quick addition, removal, copying, and pasting of environment variables.

Show Command Line for external program launch

The External Tools Configuration dialog for launching an external program now supports the Show Command Line button.

Preferences

Close editors automatically when reaching 99 open editors

The preference to close editors automatically is now enabled by default. It will be triggered when you have opened 99 files. If you continue to open editors, old editors will be closed to protect you from performance problems. You can modify this setting in the Preferences dialog via the General > Editors > Close editors automatically preference.

In-table color previews for Text Editor appearance color options

You can now see all the colors currently being used in Text Editors from the Appearance color options table, located in the Preferences > General > Editors > Text Editor page.

Automatic detection of UI freezes in the Eclipse SDK

The Eclipse SDK has been configured to show stack traces for UI freezes in the Error Log view by default for new workspaces. You can use this information to identify and report slow parts of the Eclipse IDE.

You can disable the monitoring or tweak its settings via the options in the General > UI Responsiveness Monitoring preference page as shown below.

Themes and Styling

Start automatically in dark theme based on OS theme

On Linux and Mac, Eclipse can now start automatically in dark theme when the OS theme is dark. This works by default, that is on a new workspace or when the user has not explicitly set or changed the theme in Eclipse.

Display of Help content respects OS theme

More and more operating systems provide a system-wide dark theme. Eclipse now respects this system-wide theme setting when the Eclipse help content is displayed in an external browser. A prerequisite for this is a browser that supports the prefers-color-scheme CSS media query.

As of the time of writing, the following browser versions support it:

  • Firefox version 67
  • Chrome version 76
  • Safari version 12.1

Help content uses high-resolution icons.

The Help System, as well as the help content of the Eclipse Platform, the Java Development Tooling, and the Plug-in Development Environment, now uses high-resolution icons. They are now crisp on high-resolution displays and also look much better in the dark theme.

Improved dark theme on Windows

Labels, Sections, Checkboxes, Radio Buttons, FormTexts, and Sashes on forms now use the correct background color in the dark mode on windows.

General Updates

Interactive performance

Interactive performance has been further improved in this release and several UI freezes have been fixed.

Show key bindings when command is invoked

For presentations, screencasts, and learning purposes, it is very helpful to show the corresponding key binding when a command is invoked. When the command is invoked (via a key binding or menu interaction) the key binding, the command’s name and description are shown on the screen.

You can activate this in the Preferences dialog via the Show key binding when command is invoked checkbox on the General > Keys preference page. To toggle this setting quickly, you can use the Toggle Whether to Show Key Binding command (e.g., via the quick access).

Java Developement Tools (JDT)

Java 13 Support

Java 13 is out, and Eclipse JDT supports Java 13 for 4.13 via Marketplace.

The release notably includes the following Java 13 features:

  • JEP 354: Switch Expressions (Preview).
  • JEP 355: Text Blocks (Preview).

Please note that these are preview language features; hence, the enable preview option should be on. For an informal introduction of the support, please refer to Java 13 Examples wiki.

Java Views and Dialogs

Synchronize standard and error output in console

The Eclipse Console view currently can not ensure that mixed standard and error output is shown in the same order as it is produced by the running process. For Java applications, the launch configuration Common tab now provides an option to merge standard and error output. This ensures that standard and error output is shown in the same order it was produced but also disables the individual coloring of error output.

Java Editor

Convert to enhanced ‘for’ loop using Collections

The Java quickfix/cleanup Convert to enhanced ‘for’ loop is now offered on for loops that are iterating through Collections. The loop must reference the size method as part of the condition and if accessing elements in the body, must use the get method. All other Collection methods other than isEmpty invalidate the quickfix being offered.

Initialize ‘final’ fields

A Java quickfix is now offered to initialize an uninitialized final field in the class constructor. The fix will initialize a String to the empty string, a numeric base type to 0, and, for class fields, it initializes them using their default constructor if available or null if no default constructor exists.

Autoboxing and Unboxing

Use Autoboxing and Unboxing when possible. These features are enabled only for Java 5 and higher.

Improved redundant modifier removal

The Remove redundant modifier now also removes useless abstract modifier on the interfaces.

For the given code:

You get this:

Javadoc comment generation for module

Adding a Javadoc comment to a Java module (module-info.java) will result in automatic annotations being added per the new module comment preferences.

The $(tags) directive will add @uses and @provides tags for all uses and provides module statements.

Chain Completion Code Assist

Code assist for “Chain Template Proposals” will be available. These will traverse reachable local variables, fields, and methods, to produce a chain whose return type is compatible with the expected type in a particular context.

The preference to enable the feature can be found in the Advanced sub-menu of the Content Assist menu group (Preferences > Java > Editor > Content Assist > Advanced).

Java Formatter

Remove excess blank lines

All the settings in the Blank lines section can now be configured to remove excess blank lines, effectively taking precedence over the Number of empty lines to preserve setting. Each setting has its own button to turn the feature on, right next to its number control. The button is enabled only if the selected number of lines is smaller than the Number of empty lines to preserve; otherwise, any excess lines are removed anyway.

Changes in blank lines settings

There’s quite a lot of changes in the Blank lines section of the formatter profile.

Some of the existing subsections and settings are now phrased differently to better express their function:

  • The Blank lines within class declarations subsection is now Blank lines within type declaration.
  • Before first declaration is now Before first member declaration.
  • Before declarations of the same kind is now Between member declarations of different kind.
  • Before member class declarations is now Between member type declarations.
  • Before field declarations is now Between field declarations.
  • Before method declarations is now Between method/constructor declarations.

More importantly, a few new settings have been added to support more places where the number of empty lines can be controlled:

  • After last member declaration in a type (to complement previously existing Before first member declaration setting).
  • Between abstract method declarations in a type (these cases were previously handled by Between method/constructor declarations).
  • At end of method/constructor body (to complement previously existing At beginning of method/constructor body setting).
  • At beginning of code block and At end of code block.
  • Before statement with code block and After statement with code block.
  • Between statement groups in ‘switch.’

Most of the new settings have been put in a new subsection Blank lines within method/constructor declarations.

JUnit

JUnit 5.5.1

JUnit 5.5.1 is here and Eclipse JDT has been updated to use this version.

Debug

Enhanced support for –patch-module during launch

The Java Launch Configuration now supports patching of different modules by different sources during the launch. This can be verified in the Override Dependencies…​ dialog in the Dependencies tab in a Java Launch Configuration.

Java Build

Full build on JDT core preferences change

Manually changing the settings file .settings/org.eclipse.jdt.core.prefs of a project will result in a full project build, if the workspace auto-build is on. For example, pulling different settings from a git repository or generating the settings with a tool will now trigger a build. Note that this includes timestamp changes, even if actual settings file contents were not changed.

For the 4.13 release, it is possible to disable this new behavior with the VM property: -Dorg.eclipse.disableAutoBuildOnSettingsChange=true. It is planned to remove this VM property in a future release.

And more…​

You can find more noteworthy updates in on this page.

What is next?

Having JBoss Tools 4.13.0 and Red Hat CodeReady Studio 12.13 out we are already working on the next release for Eclipse 2019-12.

Share

The post New features in Red Hat CodeReady Studio 12.13.0.GA and JBoss Tools 4.13.0.Final for Eclipse 2019-09 appeared first on Red Hat Developer.

Posted on Leave a comment

Top Programming Languages Of 2019

Every year GitHub release their State of the Octoverse report containing a huge number of insights drawn from datamining the massive number of public and private repositories on GitHub.  One of the most interesting parts of the report is always the most popular programming languages.  This year, the 10 most popular programming languages on GitHub are:

  1. JavaScript
  2. Python
  3. Java
  4. PHP
  5. C#
  6. C++
  7. TypeScript
  8. Shell
  9. C
  10. Ruby

The list was created using the following criteria:

Top 10 primary languages over time, ranked by number of unique contributors to public and private repositories tagged with the appropriate primary language.

Every year Stack Overflow have a similar report, drawn instead from a developer survey.  The language popularity reports are remarkably consistent between the two 2019 reports.

You can learn more about the reports watching the video below.

[youtube https://www.youtube.com/watch?v=mkdAoAY41T0&w=853&h=480]

GameDev News Programming


Posted on Leave a comment

Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1

Quarkus is, in its own words, “Supersonic subatomic Java” and a “Kubernetes native Java stack tailored for GraalVM & OpenJDK HotSpot, crafted from the best of breed Java libraries and standards.” For the purpose of illustrating how to modernize an existing Java application to Quarkus, I will use the Red Hat JBoss Enterprise Application Platform (JBoss EAP) quickstarts helloworld quickstart as sample of a Java application builds using technologies (CDI and Servlet 3) supported in Quarkus.

It’s important to note that both Quarkus and JBoss EAP rely on providing developers with tools based—as much as possible—on standards. If your application is not already running on JBoss EAP, there’s no problem. You can migrate it from your current application server to JBoss EAP using the Red Hat Application Migration Toolkit. After that, the final and working modernized version of the code is available in the https://github.com/mrizzi/jboss-eap-quickstarts/tree/quarkus repository inside the helloworld module.

This article is based on the guides Quarkus provides, mainly Creating Your First Application and Building a Native Executable.

Get the code

To start, clone the JBoss EAP quickstarts repository locally, running:

$ git clone https://github.com/jboss-developer/jboss-eap-quickstarts.git Cloning into 'jboss-eap-quickstarts'... remote: Enumerating objects: 148133, done. remote: Total 148133 (delta 0), reused 0 (delta 0), pack-reused 148133 Receiving objects: 100% (148133/148133), 59.90 MiB | 7.62 MiB/s, done. Resolving deltas: 100% (66476/66476), done. $ cd jboss-eap-quickstarts/helloworld/

Try plain, vanilla helloworld

The name of the quickstart is a strong clue about what this application does, but let’s follow a scientific approach in modernizing this code, so first things first: Try the application as it is.

Deploy helloworld

  1. Open a terminal and navigate to the root of the JBoss EAP directory EAP_HOME (which you can download).
  2. Start the JBoss EAP server with the default profile by typing the following command:
$ EAP_HOME/bin/standalone.sh 

Note: For Windows, use the EAP_HOME\bin\standalone.bat script.

After a few seconds, the log should look like:

[org.jboss.as] (Controller Boot Thread) WFLYSRV0025: JBoss EAP 7.2.0.GA (WildFly Core 6.0.11.Final-redhat-00001) started in 3315ms - Started 306 of 527 services (321 services are lazy, passive or on-demand)
  1. Open http://127.0.0.1:8080 in a browser, and a page like Figure 1 should appear:
The JBoss EAP home page.

Figure 1: The JBoss EAP home page.

  1. Following instructions from Build and Deploy the Quickstart, deploy the helloworld quickstart and execute (from the project root directory) the command:
$ mvn clean install wildfly:deploy 

This command should end successfully with a log like this:

[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.224 s 

The helloworld application has now been deployed for the first time in JBoss EAP in about eight seconds.

Test helloworld

Following the Access the Application guide, open http://127.0.0.1:8080/helloworld in the browser and see the application page, as shown in Figure 2:

JBoss EAP's Hello World.

Figure 2: JBoss EAP’s Hello World.

Make changes

Change the createHelloMessage(String name) input parameter from World to Marco (my ego is cheap):

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Execute again the command:

$ mvn clean install wildfly:deploy 

and then refresh the web page in the browser to check the message displayed changes, as shown in Figure 3:

JBoss EAP's Hello Marco.

Figure 3: JBoss EAP’s Hello Marco.

Undeploy helloworld and shut down

If you want to undeploy (optional) the application before shutting down JBoss EAP, run the following command:

$ mvn clean install wildfly:undeploy 

To shut down the JBoss EAP instance, enter Ctrl+C in the terminal where it’s running.

Let’s modernize helloworld

Now we can leave the original helloworld behind and update it.

Create a new branch

Create a new working branch once the quickstart project finishes executing:

$ git checkout -b quarkus 7.2.0.GA 

Change the pom.xml file

The time has come to start changing the application. starting from the pom.xml file. From the helloworld folder, run the following command to let Quarkus add XML blocks:

$ mvn io.quarkus:quarkus-maven-plugin:0.23.2:create 

This article uses the 0.23.2 version. To know which is the latest version is, please refer to https://github.com/quarkusio/quarkus/releases/latest/, since the Quarkus release cycles are short.

This command changed the pom.xml, file adding:

  • The property <quarkus.version> to define the Quarkus version to be used.
  • The <dependencyManagement> block to import the Quarkus bill of materials (BOM). In this way, there’s no need to add the version to each Quarkus dependency.
  • The quarkus-maven-plugin plugin responsible for packaging the application, and also providing the development mode.
  • The native profile to create application native executables.

Further changes required to pom.xml, to be done manually:

  1. Move the <groupId> tag outside of the <parent> block, and above the <artifactId> tag. Because we remove the <parent> block in the next step, the <groupId> must be preserved.
  2. Remove the <parent> block: The application doesn’t need the JBoss parent pom anymore to run with Quarkus.
  3. Add the <version> tag (below the <artifactId> tag) with the value you prefer.
  4. Remove the <packaging> tag: The application won’t be a WAR anymore, but a plain JAR.
  5. Change the following dependencies:
    1. Replace the javax.enterprise:cdi-api dependency with io.quarkus:quarkus-arc, removing <scope>provided</scope> because—as stated in the documentation—this Quarkus extension provides the CDI dependency injection.
    2. Replace the org.jboss.spec.javax.servlet:jboss-servlet-api_4.0_spec dependency with io.quarkus:quarkus-undertow, removing the <scope>provided</scope>, because—again as stated in the documentation—this is the Quarkus extension that provides support for servlets.
    3. Remove the org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec dependency because it’s coming with the previously changed dependencies.

The pom.xml file’s fully changed version is available at https://github.com/mrizzi/jboss-eap-quickstarts/blob/quarkus/helloworld/pom.xml.

Note that the above mvn io.quarkus:quarkus-maven-plugin:0.23.2:create command, besides the changes to the pom.xml file, added components to the project. The added file and folders are:

  • The files mvnw and mvnw.cmd, and .mvn folder: The Maven Wrapper allows you to run Maven projects with a specific version of Maven without requiring that you install that specific Maven version.
  • The docker folder (in src/main/): This folder contains example Dockerfile files for both native and jvm modes (together with a .dockerignore file).
  • The resources folder (in src/main/): This folder contains an empty application.properties file and the sample Quarkus landing page index.html (more in the section “Run the modernized helloworld“).

Run helloworld

To test the application, use quarkus:dev, which runs Quarkus in development mode (more details on Development Mode here).

Note: We expect this step to fail as changes are still required to the application, as detailed in this section.

Now run the command to check if and how it works:

$ ./mvnw compile quarkus:dev [INFO] Scanning for projects... [INFO] [INFO] ----------------< org.jboss.eap.quickstarts:helloworld >---------------- [INFO] Building Quickstart: helloworld quarkus [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 2 resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld --- Listening for transport dt_socket at address: 5005 INFO [io.qua.dep.QuarkusAugmentor] Beginning quarkus augmentation INFO [org.jbo.threads] JBoss Threads version 3.0.0.Final ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.jboss.as.quickstarts.helloworld.HelloService and qualifiers [@Default] - java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService - declared on CLASS bean [types=[javax.servlet.ServletConfig, java.io.Serializable, org.jboss.as.quickstarts.helloworld.HelloWorldServlet, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], qualifiers=[@Default, @Any], target=org.jboss.as.quickstarts.helloworld.HelloWorldServlet] at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:841) at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:214) at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:106) at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:249) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:780) at io.quarkus.builder.BuildContext.run(BuildContext.java:415) at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1426) at java.lang.Thread.run(Thread.java:748) at org.jboss.threads.JBossThread.run(JBossThread.java:479) Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.jboss.as.quickstarts.helloworld.HelloService and qualifiers [@Default] - java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService - declared on CLASS bean [types=[javax.servlet.ServletConfig, java.io.Serializable, org.jboss.as.quickstarts.helloworld.HelloWorldServlet, javax.servlet.GenericServlet, javax.servlet.Servlet, java.lang.Object, javax.servlet.http.HttpServlet], qualifiers=[@Default, @Any], target=org.jboss.as.quickstarts.helloworld.HelloWorldServlet] at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:428) at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:371) at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:206) ... 14 more 

It failed. Why? What happened?

The UnsatisfiedResolutionException exception refers to the HelloService class, which is a member of the HelloWorldServlet class (java member: org.jboss.as.quickstarts.helloworld.HelloWorldServlet#helloService). The problem is that HelloWorldServlet needs an injected instance of HelloService, but it can not be found (even if the two classes are in the very same package).

It’s time to return to Quarkus guides to leverage the documentation and understand how @Inject—and hence Contexts and Dependency Injection (CDI)—works in Quarkus, thanks to the Contexts and Dependency Injection guide. In the Bean Discovery paragraph, it says, “Bean classes that don’t have a bean defining annotation are not discovered.”

Looking at the HelloService class, it’s clear there’s no bean defining annotation, and one has to be added to have Quarkus to discover the bean. So, because it’s a stateless object, it’s safe to add the @ApplicationScoped annotation:

@ApplicationScoped public class HelloService { 

Note: The IDE should prompt you to add the required package shown here (add it manually if need be):

import javax.enterprise.context.ApplicationScoped; 

If you’re in doubt about which scope to apply when the original bean has no scope defined, please refer to the JSR 365: Contexts and Dependency Injection for Java 2.0—Default scope documentation.

Now, try again to run the application, executing again the ./mvnw compile quarkus:dev command:

$ ./mvnw compile quarkus:dev [INFO] Scanning for projects... [INFO] [INFO] ----------------< org.jboss.eap.quickstarts:helloworld >---------------- [INFO] Building Quickstart: helloworld quarkus [INFO] --------------------------------[ war ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ helloworld --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 2 resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ helloworld --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 2 source files to /home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/target/classes [INFO] [INFO] --- quarkus-maven-plugin:0.23.2:dev (default-cli) @ helloworld --- Listening for transport dt_socket at address: 5005 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus augmentation INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 576ms INFO [io.quarkus] (main) Quarkus 0.23.2 started in 1.083s. Listening on: http://0.0.0.0:8080 INFO [io.quarkus] (main) Profile dev activated. Live Coding activated. INFO [io.quarkus] (main) Installed features: [cdi] 

This time the application runs successfully.

Run the modernized helloworld

As the terminal log suggests, open a browser to http://0.0.0.0:8080(the default Quarkus landing page), and the page shown in Figure 4 appears:

The Quarkus dev landing page.

Figure 4: The Quarkus dev landing page.

This application has the following context’s definition in the WebServlet annotation:

@WebServlet("/HelloWorld") public class HelloWorldServlet extends HttpServlet { 

Hence, you can browse to http://0.0.0.0:8080/HelloWorldto reach the page shown in Figure 5:

The Quarkus dev Hello World page.

Figure 5: The Quarkus dev Hello World page.

It works!

Make changes

Please, pay attention to the fact that the ./mvnw compile quarkus:dev command is still running, and we’re not going to stop it. Now, try to apply the same—very trivial—change to the code and see how Quarkus improves the developer experience:

writer.println("<h1>" + helloService.createHelloMessage("Marco") + "</h1>");

Save the file, and then refresh the web page to check that Hello Marco appears, as shown in Figure 6:

The Quarkus dev Hello Marco page.

Figure 6: The Quarkus dev Hello Marco page.

Take time to check the terminal output:

INFO [io.qua.dev] (vert.x-worker-thread-3) Changed source files detected, recompiling [/home/mrizzi/git/forked/jboss-eap-quickstarts/helloworld/src/main/java/org/jboss/as/quickstarts/helloworld/HelloWorldServlet.java] INFO [io.quarkus] (vert.x-worker-thread-3) Quarkus stopped in 0.003s INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Beginning quarkus augmentation INFO [io.qua.dep.QuarkusAugmentor] (vert.x-worker-thread-3) Quarkus augmentation completed in 232ms INFO [io.quarkus] (vert.x-worker-thread-3) Quarkus 0.23.2 started in 0.257s. Listening on: http://0.0.0.0:8080 INFO [io.quarkus] (vert.x-worker-thread-3) Profile dev activated. Live Coding activated. INFO [io.quarkus] (vert.x-worker-thread-3) Installed features: [cdi] INFO [io.qua.dev] (vert.x-worker-thread-3) Hot replace total time: 0.371s 

Refreshing the page triggered the source code change detection and the Quarkus automagic “stop-and-start.” All of this executed in just 0.371 seconds (that’s part of the Quarkus “Supersonic Subatomic Java” experience).

Build the helloworld packaged JAR

Now that the code works as expected, it can be packaged using the command:

$ ./mvnw clean package

This command creates two JARs in the /target folder. The first is helloworld-<version>.jar, which is the standard artifact built from the Maven command with the project’s classes and resources. The second is helloworld-<version>-runner.jar, which is an executable JAR.

Please pay attention to the fact that this is not an uber-jar, because all of the dependencies are copied into the /target/lib folder (and not bundled within the JAR). Hence, to run this JAR in another location or host, both the JAR file and the libraries in the /lib folder have to be copied, considering that the Class-Path entry of the MANIFEST.MF file in the JAR explicitly lists the JARs from the lib folder.

To create an uber-jar application, please refer to the Uber-Jar Creation Quarkus guide.

Run the helloworld packaged JAR

Now, the packaged JAR can be executed using the standard java command:

$ java -jar ./target/helloworld-<version>-runner.jar INFO [io.quarkus] (main) Quarkus 0.23.2 started in 0.673s. Listening on: http://0.0.0.0:8080 INFO [io.quarkus] (main) Profile prod activated. INFO [io.quarkus] (main) Installed features: [cdi] 

As done above, open the http://0.0.0.0:8080 URL in a browser, and test that everything works.

Build the helloworld quickstart-native executable

So far so good. The helloworld quickstart ran as a standalone Java application using Quarkus dependencies, but more can be achieved by adding a further step to the modernization path: Build a native executable.

Install GraalVM

First of all, the tools for creating the native executable have to be installed:

  1. Download GraalVM 19.2.0.1 from https://github.com/oracle/graal/releases/tag/vm-19.2.0.1.
  2. Untar the file using the command:

$ tar xvzf graalvm-ce-linux-amd64-19.2.0.1.tar.gz

  1. Go to the untar folder.
  2. Execute the following to download and add the native image component:

$ ./bin/gu install native-image

  1. Set the GRAALVM_HOME environment variable to the folder created in step two, for example:

$ export GRAALVM_HOME={untar-folder}/graalvm-ce-19.2.0.1)

More details and install instructions for other operating systems are available in Building a Native Executable—Prerequisites Quarkus guide.

Build the helloworld native executable

As stated in the Building a Native Executable—Producing a native executable Quarkus guide, “Let’s now produce a native executable for our application. It improves the startup time of the application and produces a minimal disk footprint. The executable would have everything to run the application including the ‘JVM’ (shrunk to be just enough to run the application), and the application.”

To create the native executable, the Maven native profile has to be enabled by executing:

$ ./mvnw package -Pnative

The build took me about 1:10 minutes and the result is the helloworld-<version>-runner file in the /target folder.

Run the helloworld native executable

The /target/helloworld-<version>-runner file created in the previous step. It’s executable, so running it is easy:

$ ./target/helloworld-<version>-runner INFO [io.quarkus] (main) Quarkus 0.23.2 started in 0.006s. Listening on: http://0.0.0.0:8080 INFO [io.quarkus] (main) Profile prod activated. INFO [io.quarkus] (main) Installed features: [cdi] 

As done before, open the http://0.0.0.0:8080 URL in a browser and test that everything is working.

Next steps

I believe that this modernization, even of a basic application, is the right way to approach a brownfield application using technologies available in Quarkus. This way, you can start facing the issues and tackling them to understand and learn how to solve them.

In part two of this series, I’ll look at how to capture memory consumption data in order to evaluate performance improvements, which is a fundamental part of the modernization process.

Share

The post Quarkus: Modernize “helloworld” JBoss EAP quickstart, Part 1 appeared first on Red Hat Developer.

Posted on Leave a comment

Managing JBoss EAP/Wildfly using Jcliff

Systems management can be a difficult task. Not only does one need to determine what the end state should be but, more importantly, how to ensure systems attain and remain at this state. Doing so in an automated fashion is just as critical, because there may be a large number of target instances. In regard to enterprise Java middleware application servers, these instances are typically configured using a set of XML based files. Although these files may be manually configured, most application servers have a command-line based tool or set of tools that abstracts the end user from having to worry about the underlying configuration. WebSphere Liberty includes a variety of tools to manage these resources, whereas JBoss contains the jboss-cli tool.

Although each tool accomplishes its utilitarian use case as it allows for proper server management, it does fail to adhere to one of the principles of automation and configuration management: idempotence. Ensuring the desired state does not equate to executing the same action with every iteration. Additional intelligence must be introduced. Along with idempotence, another core principle of configuration management is that values be expressed declaratively and stored in a version control system.

Jcliff is a Java-based utility that is built on top of the JBoss command-line interface and allows for the desired intent for the server configuration to be expressed declaratively, which in turn can be stored in a version control system. We’ll provide an overview of the Jcliff utility including inherent benefits, installation options, and several examples showcasing the use.

The problem space

Before beginning to work with Jcliff, one must be cognizant of the underlying JBoss architecture. The configuration of the JBoss server can be expressed using Dynamic Model Representation (DMR) notation. The following is an example of DMR:

{ "system-property" => { "foo" => "bar", "bah" => "gah" } } 

The DMR example above describes several Java system properties that will be stored within the JBoss configuration. These properties can be added using the JBoss CLI by executing the following command:

/system-property=foo:add(value=bar) /system-property=bah:add(value=gah) 

The challenge is that the same commands cannot be executed more than once. Otherwise, an error similar to the following is produced.

{ "outcome" => "failed", "failure-description" => "WFLYCTL0212: Duplicate resource [(\"system-property\" => \"foo\")]", "rolled-back" => true } 

Where Jcliff excels is that it includes the necessary intelligence to determine the current state of the JBoss configuration and then applying the appropriate configurations necessary. This is critical to adopting proper configuration management when working with JBoss.

Installing Jcliff

With a baseline understanding of Jcliff, let’s discuss the methods in which one can obtain the utility. First, Jcliff can be built from source from the project repository, given that it’s a freely open source project. Alternatively, Jcliff can be installed using popular software packaging tools in each of the primary operating system families.

Linux (rpm)

Jcliff can be consumed on a Linux package when capable of consuming an rpm using a package manager.

First, install the yum repository:

$ cat /etc/yum.repos.d/jcliff.repo [jcliff] baseurl = http://people.redhat.com/~rpelisse/jcliff.yum/ gpgcheck = 0 name = JCliff repository 

Once this repository has been added, JCliff can be installed by using Yum or Dnf:

Using yum:

$ sudo yum install jcliff 

Or using dnf:

$ sudo dnf install jcliff 

Manual installation

Jcliff can also be installed manually without the need to leverage a package manager. This is useful for those on Linux distributions that cannot consume rpm packages. Simply download and unpack the archive from the release artifact from the project repository.

$ curl -O \ https://github.com/bserdar/jcliff/releases/download/v2.12.1/jcliff-2.12.1-dist.tar.gz $ tar xzvf jcliff-2.12.1-dist.tar.gz 

Place the resulting Jcliff folder in the destination of your choosing. This location is known as JCLIFF_HOME. Add this environment variable and add it to the path as described below:

$ export JCLIFF_HOME=/path/to/jcliff-2.12.1/ $ export PATH=${JCLIFF_HOME}/bin:${PATH} 

At this point, you should be able to execute the jcliff command.

OSX

While users on OSX can take advantage of the manual installation option, those making use of the brew package manager can use this tool as well.

Execute the following commands to install Jcliff using Brew:

$ brew tap redhat-cop/redhat-cop $ brew install redhat-cop/redhat-cop/jcliff 

Windows

Fear not, Windows users; you can also make use of Jcliff without having to compile from source. Windows, in the same vein as OSX, does not have an official package manager, but Chocolatey has been given this role.

Execute the following command to install Jcliff using Chocolatey:

$ choco install jcliff 

Using Jcliff

With Jcliff properly installed on your machine, let’s walk through a simple example to demonstrate the use of the tool. As discussed previously, Jcliff makes use of files that describe the target configuration. At this point, you may have questions like: What is the format of these configurations, and where do I begin?

Let’s take a simple example and look into adding a new system property to the JBoss configuration. Launch an instance of JBoss and connect using the JBoss command-line interface:

$ /bin/jboss-cli.sh --connect [standalone@localhost:9990 /] ls /system-property [standalone@localhost:9990 /] 

Now, use Jcliff to update the configuration. First, we’ll need to create a Jcliff rule. The rule resembles DMR format and appears similar to the following:

$ cat jcliff-prop { "system-property" => { "jcliff.enabled" => "true", } } 

Then we can simply ask JCliff to run this script against our JBoss server:

$ jcliff jcliff-prop Jcliff version 2.12.4 2019-10-02 17:03:40:0008: /core-service=platform-mbean/type=runtime:read-attribute(name=system-properties) 2019-10-02 17:03:41:0974: /system-property=jcliff.enabled:add(value="true") 

Use the JBoss CLI to verify the changes have been applied.

$ “${JBOSS_HOME}/bin/jboss-cli.sh” --connect --command=/system-property=jcliff.enabled:read-resource { "outcome" => "success", "result" => {"value" => "true"} } 

To demonstrate how Jcliff handles repetitive executions, run the previous Jcliff command again. Inspect the output.

$ jcliff jcliff-prop Jcliff version 2.12.4 2019-10-02 17:05:34:0107: /core-service=platform-mbean/type=runtime:read-attribute(name=system-properties) 

Notice that only 1 command was executed against the JBoss server instead of two? This action was a result of assessing the current state within JBoss and determining that no action was necessary to reach the desired state. Mission accomplished.

Next steps

Although the preceding scenario was not overly complex, you should now have the knowledge necessary to understand the capabilities and functionality of the Jcliff utility as well as the benefits afforded through declarative configurations and automation. When building out enterprise-grade systems, however, Jcliff would not be executed manually. You would want to integrate the utility into a proper configuration management tool that employs many of the automation and configuration principles described earlier. Fortunately, Jcliff has been integrated into several popular configuration management tools.

In an upcoming article, we’ll provide an overview of the configuration management options available with Jcliff, along with examples that will allow you to quickly build out enterprise-grade confidence with Jcliff.

Share

The post Managing JBoss EAP/Wildfly using Jcliff appeared first on Red Hat Developer.

Posted on Leave a comment

ASP.NET Core updates in .NET Core 3.1 Preview 2

Daniel Roth

Daniel

.NET Core 3.1 Preview 2 is now available. This release is primarily focused on bug fixes, but it contains a few new features as well.

Here’s what’s new in this release for ASP.NET Core:

  • New component tag helper
  • Prevent default actions for events in Blazor apps
  • Stop event propagation in Blazor apps
  • Validation of nested models in Blazor forms
  • Detailed errors during Blazor app development

See the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.1 Preview 2 install the .NET Core 3.1 Preview 2 SDK.

If you’re on Windows using Visual Studio, for the best experience we recommend installing the latest preview of Visual Studio 2019 16.4. Installing Visual Studio 2019 16.4 will also install .NET Core 3.1 Preview 2, so you don’t need to separately install it. For Blazor development with .NET Core 3.1, Visual Studio 2019 16.4 is required.

Alongside this .NET Core 3.1 Preview 2 release, we’ve also released a Blazor WebAssembly update. To install the latest Blazor WebAssembly template also run the following command:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview2.19528.8

Upgrade an existing project

To upgrade an existing ASP.NET Core 3.1 Preview 1 project to 3.1 Preview 2:

  • Update all Microsoft.AspNetCore.* package references to 3.1.0-preview2.19528.8

See also the full list of breaking changes in ASP.NET Core 3.1.

That’s it! You should now be all set to use .NET Core 3.1 Preview 2!

New component tag helper

Using Razor components from views and pages is now more convenient with the new component tag helper.

Previously, rendering a component from a view or page involved using the RenderComponentAsync HTML helper.

@(await Html.RenderComponentAsync<Counter>(RenderMode.ServerPrerendered, new { IncrementAmount = 10 }))

The new component tag helper simplifies the syntax for rendering components from pages and views. Simply specify the type of the component you wish to render as well as the desired render mode. You can also specify component parameters using attributes prefixed with param-.

<component type="typeof(Counter)" render-mode="ServerPrerendered" param-IncrementAmount="10" />

The different render modes allow you to control how the component is rendered:

RenderMode Description
Static Renders the component into static HTML.
Server Renders a marker for a Blazor Server application. This doesn’t include any output from the component. When the user-agent starts, it uses this marker to bootstrap the Blazor app.
ServerPrerendered Renders the component into static HTML and includes a marker for a Blazor Server app. When the user-agent starts, it uses this marker to bootstrap the Blazor app.

Prevent default actions for events in Blazor apps

You can now prevent the default action for events in Blazor apps using the new @oneventname:preventDefault directive attribute. For example, the following component displays a count in a text box that can be changed by pressing the “+” or “-” keys:

<p>Press "+" or "-" in change the count.</p>
<input value="@count" @onkeypress="@KeyHandler" @onkeypress:preventDefault /> @code { int count = 0; void KeyHandler(KeyboardEventArgs ev) { if (ev.Key == "+") { count++; } else if (ev.Key == "-") { count--; } }
}

The @onkeypress:preventDefault directive attribute prevents the default action of showing the text typed by the user in the text box. Specifying this attribute without a value is equivalent to @onkeypress:preventDefault="true". The value of the attribute can also be an expression: @onkeypress:preventDefault="shouldPreventDefault". You don’t have to define an event handler to prevent the default action; both features can be used independently.

Stop event propagation in Blazor apps

Use the new @oneventname:stopPropagation directive attribute to stop event propagation in Blazor apps.

In the following example, checking the checkbox prevents click events from the child div from propagating to the parent div:

<input @bind="stopPropagation" type="checkbox" />
Parent div
Child div
</div> <button @onclick="OnClick">Click me!</button> @code { bool stopPropagation; void OnClickParentDiv() => Console.WriteLine("Parent div clicked."); void OnClickChildDiv() => Console.WriteLine("Child div clicked."); }

Detailed errors during Blazor app development

When your Blazor app isn’t functioning properly during development, it’s important to get detailed error information so that you can troubleshoot and fix the issues. Blazor apps now display a gold bar at the bottom of the screen when an error occurs.

During development, in Blazor Server apps, the gold bar will direct you to the browser console where you can see the exception that has occurred.

Blazor detailed errors in development

In production, the gold bar notifies the user that something has gone wrong, and recommends the user to refresh the browser.

Blazor detailed errors in production

The UI for this error handling experience is part of the updated Blazor project templates so that it can be easily customized:

_Host.cshtml

An error has occurred. This application may no longer respond until reloaded. An unhandled exception has occurred. See browser dev tools for details. Reload 🗙

Validation of nested models in Blazor forms

Blazor provides support for validating form input using data annotations with the built-in DataAnnotationsValidator. However, the DataAnnotationsValidator only validates top-level properties of the model bound to the form.

To validate the entire object graph of the bound model, try out the new ObjectGraphDataAnnotationsValidator available in the experimental Microsoft.AspNetCore.Blazor.DataAnnotations.Validation package:

<EditForm Model="@model" OnValidSubmit="@HandleValidSubmit"> <ObjectGraphDataAnnotationsValidator /> ...
</EditForm>

The Microsoft.AspNetCore.Blazor.DataAnnotations.Validation is not slated to ship with .NET Core 3.1, but is provided as an experimental package to get early feedback.

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core! Please let us know what you think by filing issues on GitHub.

Thanks for trying out ASP.NET Core!

Daniel Roth
Daniel Roth

Principal Program Manager, ASP.NET

Follow Daniel   

Posted on Leave a comment

Vulkan Unified Samples Repository

The Khronos Group have just released the Vulkan Unified Samples Repository, a single location for the best tutorials and code samples for learning and using the Vulkan API.

Details from the Khronos blog:

Today, The Khronos® Group releases the Vulkan ® Unified Samples Repository, a new central location where anyone can access Khronos-reviewed, high-quality Vulkan code samples in order to make development easier and more streamlined for all abilities. Khronos and its members, in collaboration with external contributors, created the Vulkan Unified Samples Project in response to user demand for more accessible resources and best practices for developing with Vulkan. Within Khronos, the Vulkan Working Group discovered that there were many useful and high-quality samples available already (both from members and external contributors), but they were not all in one central location. Additionally, there was no top-level review of all the samples for interoperability or compatibility. This new repository project was created to solve this challenge by putting resources in one place, ensuring samples are reviewed and maintained by Khronos. They are then organized into a central library available for developers of all abilities to use, learn from, and gain ideas.

The first group of samples includes a generous donation of performance-based samples and best practice documents from Khronos member, Arm.

The repository is hosted entirely on GitHub under the Apache 2.0 source license.  The code samples are located here.

You can learn more in the video below.

[youtube https://www.youtube.com/watch?v=McpET2clPS0&w=853&h=480]

GameDev News Programming


Posted on Leave a comment

Haxe 4.0.0 Released

The Haxe Programming Language just hit a major milestone with the release of version 4.0.0.  The programming language gains several new features such as:

  • New function type syntax
  • Arrow function syntax
  • final keyword
  • New and faster Haxe built-in interpreter
  • Unicode support on all targets
  • Key-value iterators
  • Auto-“using” for types
  • IDE services protocol for better IDE support
  • New high-performance run-time HashLink, a successor of Neko
  • .. and much more!

Check the complete What’s New Guide for a full list of changes in this release, including possible breaking changes from Haxe 3.x.  There is a thriving ecosystem of game engines and frameworks for Haxe which we showcased here.  Of particular interest are the Blender based Armory3D engine (tutorial series here) and the popular and mature 2D frame HaxeFlixel (tutorial series here).

You can learn more about the Haxe 4.0.0 release in the video below.

[youtube https://www.youtube.com/watch?v=9KW6P9JaqTc&w=853&h=480]

GameDev News Programming


Posted on Leave a comment

Bring joy to development with Quarkus, the cloud-native Java framework

Our first DevNation Live regional event was held in Bengaluru, India in July. This free technology event focused on open source innovations, with sessions presented by elite Red Hat technologists.

Quarkus is revolutionizing the way that we develop Java applications for the cloud-native era, and in this presentation, Edson Yanaga explains why it also sparks joy.

Watch this live coding session to get familiar with Quarkus and learn how your old and new favorite APIs will start in a matter of milliseconds and consume tiny amounts of memory. Hot reload capabilities for development will bring you instant joy.

Watch the complete presentation:

See the slides here.

Learn more

Join us at an upcoming developer event, and see our collection of past DevNation Live tech talks.

Share

The post Bring joy to development with Quarkus, the cloud-native Java framework appeared first on Red Hat Developer.

Posted on Leave a comment

Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core

Avatar

Barry

SameSite is a 2016 extension to HTTP cookies intended to mitigate cross site request forgery (CSRF). The original design was an opt-in feature which could be used by adding a new SameSite property to cookies. It had two values, Lax and Strict. Setting the value to Lax indicated the cookie should be sent on navigation within the same site, or through GET navigation to your site from other sites. A value of Strict limited the cookie to requests which only originated from the same site. Not setting the property at all placed no restrictions on how the cookie flowed in requests. OpenIdConnect authentication operations (e.g. login, logout), and other features that send POST requests from an external site to the site requesting the operation, can use cookies for correlation and/or CSRF protection. These operations would need to opt-out of SameSite, by not setting the property at all, to ensure these cookies will be sent during their specialized request flows.

Google is now updating the standard and implementing their proposed changes in an upcoming version of Chrome. The change adds a new SameSite value, “None”, and changes the default behavior to “Lax”. This breaks OpenIdConnect logins, and potentially other features your web site may rely on, these features will have to use cookies whose SameSite property is set to a value of “None”. However browsers which adhere to the original standard and are unaware of the new value have a different behavior to browsers which use the new standard as the SameSite standard states that if a browser sees a value for SameSite it does not understand it should treat that value as “Strict”. This means your .NET website will now have to add user agent sniffing to decide whether you send the new None value, or not send the attribute at all.

.NET will issue updates to change the behavior of its SameSite attribute behavior in .NET 4.7.2 and in .NET Core 2.1 and above to reflect Google’s introduction of a new value. The updates for the .NET Framework will be available on November 19th as an optional update via Microsoft Update and WSUS if you use the “Check for Update” functionality. On December 10th it will become widely available and appear in Microsoft Update without you having to specifically check for updates. .NET Core updates will be available with .NET Core 3.1 starting with preview 1, in November.

.NET Core 3.1 will contain an updated enum definition, SameSite.Unspecified which will not set the SameSite property.

The OpenIdConnect middleware for Microsoft.Owin v4.1 and .NET Core will be updated at the same time as their .NET Framework and .NET updates, however we cannot introduce the user agent sniffing code into the framework, this must be implemented in your site code. The implementation of agent sniffing will vary according to what version of ASP.NET or ASP.NET Core you are using and the browsers you wish to support.

For ASP.NET 4.7.2 with Microsoft.Owin 4.1.0 agent sniffing can be implemented using ICookieManager;

public class SameSiteCookieManager : ICookieManager
{ private readonly ICookieManager _innerManager; public SameSiteCookieManager() : this(new CookieManager()) { } public SameSiteCookieManager(ICookieManager innerManager) { _innerManager = innerManager; } public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options) { CheckSameSite(context, options); _innerManager.AppendResponseCookie(context, key, value, options); } public void DeleteCookie(IOwinContext context, string key, CookieOptions options) { CheckSameSite(context, options); _innerManager.DeleteCookie(context, key, options); } public string GetRequestCookie(IOwinContext context, string key) { return _innerManager.GetRequestCookie(context, key); } private void CheckSameSite(IOwinContext context, CookieOptions options) { if (DisallowsSameSiteNone(context) && options.SameSite == SameSiteMode.None) { options.SameSite = null; } } public static bool DisallowsSameSiteNone(IOwinContext context) { // TODO: Use your User Agent library of choice here. var userAgent = context.Request.Headers["User-Agent"]; return userAgent.Contains("BrokenUserAgent") || userAgent.Contains("BrokenUserAgent2") }
}

And then configure OpenIdConnect settings to use the new CookieManager;

app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // … Your preexisting options … CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
});

SystemWebCookieManager will need the .NET 4.7.2 or later SameSite patch installed to work correctly.

For ASP.NET Core you should install the patches and then implement the agent sniffing code within a cookie policy. For versions prior to 3.1 replace SameSiteMode.Unspecified with (SameSiteMode)(-1).

private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{ if (options.SameSite > SameSiteMode.Unspecified) { var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); // TODO: Use your User Agent library of choice here. if (/* UserAgent doesn’t support new behavior */) { // For .NET Core < 3.1 set SameSite = -1 options.SameSite = SameSiteMode.Unspecified; } }
} public void ConfigureServices(IServiceCollection services)
{ services.Configure<CookiePolicyOptions>(options => { options.MinimumSameSitePolicy = SameSiteMode.Unspecified; options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); });
} public void Configure(IApplicationBuilder app)
{ app.UseCookiePolicy(); // Before UseAuthentication or anything else that writes cookies. app.UseAuthentication(); // …
}

Under testing with the Azure Active Directory team we have found the following checks work for all the common user agents that Azure Active Directory sees that don’t understand the new value.

public static bool DisallowsSameSiteNone(string userAgent)
{
    // Cover all iOS based browsers here. This includes:
    // - Safari on iOS 12 for iPhone, iPod Touch, iPad
    // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
    // - Chrome on iOS 12 for iPhone, iPod Touch, iPad
    // All of which are broken by SameSite=None, because they use the iOS networking stack
    if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))
    {
        return true;
    }     // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
    // - Safari on Mac OS X.
    // This does not include:
    // - Chrome on Mac OS X
    // Because they do not use the Mac OS networking stack.
    if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&  userAgent.Contains("Version/") && userAgent.Contains("Safari"))
    {
        return true;
    }     // Cover Chrome 50-69, because some versions are broken by SameSite=None,  // and none in this range require it.
    // Note: this covers some pre-Chromium Edge versions,  // but pre-Chromium Edge does not require SameSite=None.
    if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
    {
        return true;
    }     return false;
}

This browser list is by no means canonical and you should validate that the common browsers and other user agents your system supports behave as expected once the update is in place.

Chrome 80 is scheduled to turn on the new behavior in February or March 2020, including a temporary mitigation added in Chrome 79 Beta. If you want to test the new behavior without the mitigation use Chromium 76. Older versions of Chromium are available for download.

If you cannot update your framework versions by the time Chrome turns the new behavior in early 2020 you may be able to change your OpenIdConnect flow to a Code flow, rather than the default implicit flow that ASP.NET and ASP.NET Core uses, but this should be viewed as a temporary measure.

We strongly encourage you to download the updated .NET Framework and .NET Core versions when they become available in November and start planning your update before Chrome’s changes are rolled out.

Avatar