Set application version in SCDF from Java DSL - spring-cloud-dataflow

I'm trying to deploy a stream using Java DSL.
Here the code that creates stream (fluent style)
private void create() {
builder
.name(this.STREAM_NAME)
.source(source)
.sink(sink)
.create();
}
deployment method
private void deploy() {
dataFlowOperations.streamOperations().deploy(this.STREAM_NAME, new HashMap());
waitForStatus("deployed");
}
and a method that creates a bean for source application
#Bean
public StreamApplication source() {
return new StreamApplication("httpsource")
.addProperty("app.httpsource.version", "0.0.17")
.addProperty("spring.cloud.dataflow.httpsource.validation.schema", this.properties.getHttpSource().getJsonSchema());
}
I first trigger create method, then deploy. The problem is - I want to set application version to 0.0.17 for httpsource application, but final pod that is deployed for this app has image version equal to default version 0.0.1. Is it possible to set application version with Java DSL?

When deploying streams/tasks, optionally, you can pass in the version parameters as part of the deployment properties. Specifically, for versions, you'd pass them with the version.<APP_NAME> convention.
The DataflowIT presents such test combinations (see: sample); feel free to use it for reference. We rely on these tests for IT and as well as end-to-end Acceptance Tests.

Related

Hangfire job on Console/Web App solution?

I'm new to Hangfire and I'm trying to understand how this works.
So I have a MVC 5 application and a Console application in the same solution. The console application is a simple one that just updates some data on the database (originally planned to use Windows Task Scheduler).
Where exactly do I install Hangfire? In the Web app or the console? Or should I convert the console into a class on the Web app?
If I understand it correctly, the console in your solution is acting like an "pseudo" HangFire, since like you said it does some database operations overtime and you plan to execute it using the Task Scheduler.
HangFire Overview
HangFire was design to do exactly what you want with your console app, but with a lot more of power and functionalities, so you avoid all the overhead of creating all that by yourself.
HangFire Instalation
HangFire is installed commonly alongside with ASP.NET Applications, but if you carefully read the docs, you will surprisingly find this:
Hangfire project consists of a couple of NuGet packages available on
NuGet Gallery site. Here is the list of basic packages you should know
about:
Hangfire – bootstrapper package that is intended to be installed only
for ASP.NET applications that uses SQL Server as a job storage. It
simply references to Hangfire.Core, Hangfire.SqlServer and
Microsoft.Owin.Host.SystemWeb packages.
Hangfire.Core – basic package
that contains all core components of Hangfire. It can be used in any
project type, including ASP.NET application, Windows Service, Console,
any OWIN-compatible web application, Azure Worker Role, etc.
As you can see, HangFire can be used in any type of project including console applications but you will need to manage and add all the libraries depending on what kind of job storage you will use. See more here:
Once HangFire is Installed you can configure it to use the dashboard, which is an interface where you can find all the information about your background jobs. In the company I work, we used HangFire several times with recurring jobs mostly to import users, synchronize information across applications and perform operations that would be costly to run during business hours, and the Dashboard proved to be very useful when we wanted to know if a certain job was running or not. It also uses CRON to schedule the operations.
A sample of we are using right now is:
Startup.cs
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
//Get the connection string of the HangFire database
GlobalConfiguration.Configuration.UseSqlServerStorage(connection);
//Start HangFire Server and enable the Dashboard
app.UseHangfireDashboard();
app.UseHangfireServer();
//Start HangFire Recurring Jobs
HangfireServices.Instance.StartSendDetails();
HangfireServices.Instance.StartDeleteDetails();
}
}
HangfireServices.cs
public class HangfireServices
{
//.. dependency injection and other definitions
//ID of the Recurring JOBS
public static string SEND_SERVICE = "Send";
public static string DELETE_SERVICE = "Delete";
public void StartSend()
{
RecurringJob.AddOrUpdate(SEND_SERVICE, () =>
Business.Send(), //this is my class that does the actual process
HangFireConfiguration.Instance.SendCron.Record); //this is a simple class that reads an configuration CRON file
}
public void StartDeleteDetails()
{
RecurringJob.AddOrUpdate(DELETE_SERVICE, () =>
Business.SendDelete(), //this is my class that does the actual process
HangFireConfiguration.Instance.DeleteCron.Record); //this is a simple class that reads an configuration CRON file
}
}
HangFireConfiguration.cs
public sealed class HangFireConfiguration : ConfigurationSection
{
private static HangFireConfiguration _instance;
public static HangFireConfiguration Instance
{
get { return _instance ?? (_instance = (HangFireConfiguration)WebConfigurationManager.GetSection("hangfire")); }
}
[ConfigurationProperty("send_cron", IsRequired = true)]
public CronElements SendCron
{
get { return (CronElements)base["send_cron"]; }
set { base["send_cron"] = value; }
}
[ConfigurationProperty("delete_cron", IsRequired = true)]
public CronElements DeleteCron
{
get { return (CronElements)base["delete_cron"]; }
set { base["delete_cron"] = value; }
}
}
hangfire.config
<hangfire>
<send_cron record="0,15,30,45 * * * *"></send_cron>
<delete_cron record="0,15,30,45 * * * *"></delete_cron>
</hangfire>
The CRON expression above will run at 0,15,30,45 minutes every hour every day.
Web.config
<configSections>
<!-- Points to the HangFireConfiguration class -->
<section name="hangfire" type="MyProject.Configuration.HangFireConfiguration" />
</configSections>
<!-- Points to the .config file -->
<hangfire configSource="Configs\hangfire.config" />
Conclusion
Given the scenario you described, I would probably install HangFire in your ASP.NET MVC application and remove the console application, simple because it is one project less to worry about. Even though you can install it on a console application I would rather not follow that path because if you hit a brick wall (and you'll hit, trust me), chances are you'll find help mostly for cases where it was installed in ASP.NET applications.
No need of any more console application to update the database. You can use hangfire in your MVC application itself.
http://docs.hangfire.io/en/latest/configuration/index.html
After adding the hangfire configuration, you can make use of normal MVC method to do the console operations like updating the DB.
Based on your requirement you can use
BackgroundJob.Enqueue --> Immediate update to DB
BackgroundJob.Schedule --> Delayed update to DB
RecurringJob.AddOrUpdate --> Recurring update to DB like windows service.
Below is an example,
public class MyController : Controller
{
public void MyMVCMethod(int Id)
{
BackgroundJob.Enqueue(() => UpdateDB(Id));
}
public void UpdateDB(Id)
{
// Code to update the Database.
}
}

Switching from Rhino to Nashorn

I have a Java 7 project which makes a lot of use of Javascript for scripting various features. Until now I was using Rhino as script engine. I would now like to move to Java 8, which also means that I will replace Rhino by Nashorn.
How compatible is Nashorn to Rhino? Can I use it as a drop-in replacement, or can I expect that some of my scripts will not work anymore and will need to be ported to the new engine? Are there any commonly-used features of Rhino which are not supported by Nashorn?
One problem is that Nashorn can no longer by default import whole Java packages into the global scope by using importPackage(com.organization.project.package);
There is, however, a simple workaround: By adding this line to your script, you can enable the old behavior of Rhino:
load("nashorn:mozilla_compat.js");
Another problem I ran into is that certain type-conversions when passing data between java and javascript work differently. For example, the object which arrives when you pass a Javascript array to Java can no longer be cast to List, but it can be cast to a Map<String, Object>. As a workaround you can convert the Javascript array to a Java List in the Javascript code using Java.to(array, Java.type("java.util.List"))
To use the importClass method on JDK 8, we need to add the following command:
load("nashorn:mozilla_compat.js");
However, this change affect the execution on JDK 7 (JDK does not gives support to load method).
To maintain the compatibility for both SDKs, I solved this problem adding try/catch clause:
try{
load("nashorn:mozilla_compat.js");
}catch(e){
}
Nashorn can not access an inner class when that inner class is declared private, which Rhino was able to do:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.run();
}
public void run() {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
Inner inner = new Inner();
engine.put("inner", inner);
try {
engine.eval("function run(inner){inner.foo(\"test\");} run(inner);");
} catch (ScriptException e) {
e.printStackTrace();
}
}
private class Inner {
public void foo(String msg) {
System.out.println(msg);
}
}
}
Under Java8 this code throws following exception:
javax.script.ScriptException: TypeError: kz.test.Test$Inner#117cd4b has no such function "foo" in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:564)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:548)
I noticed that Rhino didn't have a problem with a function called 'in()' (although 'in' is a reserved JavaScript keyword).
Nashorn however raise an error.
Nashorn cannot call static methods on instances! Rhino did this, therefore we had to backport Rhino to Java 8 (Here's a short summary: http://andreas.haufler.info/2015/04/using-rhino-with-java-8.html)
Nashorn on Java8 does not support AST. So if you have Java code that inspects the JS source tree using Rhino's AST mechanism , you may have to rewrite it (using regex maybe) once you port your code to use Nashorn.
I am talking about this API https://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/ast/AstNode.html
Nashorn on Java9 supports AST though.
One feature that is in Rhino and not Nashorn: exposing static members through instances.
From http://nashorn-dev.openjdk.java.narkive.com/n0jtdHc9/bug-report-can-t-call-static-methods-on-a-java-class-instance : "
My conviction is that exposing static members through instances is a
sloppy mashing together of otherwise separate namespaces, hence I
chose not to enable it.
I think this is deeply wrong. As long as we have to use two different constructs to access the same java object and use package declarations unnecessarily in javascript, code becomes harder to read and write because cognitive load increases. I will rather stick to Rhino then.
I have not found a workaround for this obvious "design bug" yet.

Using Drools-Gorm plugin for Grails > 2.x.x without customizations

I'm using Drools-Gorm plugin. A bit of code from this plugin:
Domain
class SessionInfoDomain implements SessionInfo {
...
Environment env
static transients = ['env']
...
}
Service
class GormDomainService {
def SessionInfo getNewSessionInfo(Environment env) {
return new SessionInfoDomain(env: env)
}
}
But this plugin doesn't work with Grails>2.0.2 because:
Grails 2.0.2 Data Binding Improvements see link
In Grails 2.0.2 the data binding mechanism will by default exclude all properties which are static, transient or dynamically typed, so we get SessionInfoDomain without env. We can add ( bindable:true ) in constraints of SessionInfoDomain.
My question: how to ease apply this plugin to my App without change plugin?

Convention Based Dependency Injection with Ninject 3.0.0

I have two projects in my solution... a domain project and MVC3 web project (e.g. MyApp.Domain and MyApp.Web). Previously, when using Ninject.Extensions.Conventions ver. 2, I was able to use the following statement in the NinjectMVC3.cs file, and required dependencies throughout my solution (both web and domain) were injected properly (e.g. IFoo automatically bound to Foo).
kernel.Scan(x =>
{
x.FromAssembliesMatching("*");
x.BindWith<DefaultBindingGenerator>();
});
I have just upgraded to Ninject 3.0.0 (pre-release) and Ninject.Extensions.Conventions 3.0.0 (another pre-release) but the syntax for convention based binding has changed. I have figured out that I can use the following statement with the new version, but it only automatically binds the convention based interfaces in MyApp.Web and not in MyApp.Domain. The previous version bound interfaces throughout the application.
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.BindToAllInterfaces());
Any clue how I can configure convention based binding with the new Ninject version? I assume it has to do with specifying the assembly, but I have tried using FromAssembliesMatching("*") and it fails for everything then.
-- Edit to show my exisiting code in RegisterServices method: --
private static void RegisterServices(IKernel kernel)
{
// This code used to work with v.2 of Ninject.Extensions.Conventions
// kernel.Scan(x =>
// {
// x.FromAssembliesMatching("*");
// x.BindWith<DefaultBindingGenerator>();
// });
// This is the new v3 code that automatically injects dependencies but only for interfaces in MyApp.Web, not MyApp.Domain
kernel.Bind(x => x.FromThisAssembly().SelectAllClasses().BindToAllInterfaces());
// I tried this code, but it throws "Error activating IDependencyResolver" at "bootstrapper.Initialize(CreateKernel)"
// kernel.Bind(x => x.FromAssembliesInPath(AppDomain.CurrentDomain.RelativeSearchPath).SelectAllClasses().BindToAllInterfaces());
// These are dependencies in MyApp.Web that ARE being bound properly by the current configuration
// kernel.Bind<IMemberQueries>().To<MemberQueries>();
// kernel.Bind<IGrantApplicationQueries>().To<GrantApplicationQueries>();
// kernel.Bind<IMailController>().To<MailController>();
// These are dependencies in MyApp.Domain that ARE NOT being bound properly by the current configuration, so I have to declare them manually
// They used to be injected automatically with version 2 of the conventions extention
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IMemberServices>().To<MemberServices>();
kernel.Bind<IGrantApplicationServices>().To<GrantApplicationServices>();
// These are dependencies that SHOULD NOT be bound by convention as they require a different scope or have unique naming
kernel.Bind(typeof(EfDbContext)).ToSelf().InRequestScope();
kernel.Bind<IConfigurationProvider>().To<WebConfigConfigurationProvider>().InSingletonScope();
kernel.Bind<IAuthorizationProvider>().To<MyAppAuthorizationProvider>();
kernel.Bind<IPrincipal>().ToMethod(ctx => HttpContext.Current.User).InRequestScope();
kernel.Bind<IGrantApplicationDocumentServices>().To<MySpecialNameGrantAplicationDocumentServices>().InRequestScope();
}
The equivalent is:
kernel.Bind(x => x
.FromAssembliesMatching("*")
.SelectAllClasses()
.BindDefaultInterface());

Spring .Net Configuration Fluently

I have the need to use Spring .Net in a project and am exploring configuration options. All I can find about config for Spring .Net is config file stuff. Does Spring support configuration in code? I have used Castle and Ninject, and both seem to offer this natively. I have found projects that claim to add support, but I dont want some knock off project that will die in 6 months. I have found references in blogs that seem to indicate Spring supports this but I cant find any documentation!!
Part 2 of this might be would you recommend Spring .Net over Windsor knowing it cant support fluent configuration? I know both are great IoC containers, but I have worked on projects that have massive config files for Spring configuration and I hate it.
No, the current version (1.3) of Spring.NET only supports XML configuration. There has been talk about supporting Code as Configuration in future versions, but this has not yet materialized.
In my opinion, Castle Windsor is far superior to Spring.NET. I can't think of a single feature of Spring.NET that Castle Windsor doesn't have. On the other hand, Castle Windsor has the following features that are not available in Spring.NET:
Code as Configuration
Convention-based configuration
More lifetimes
Custom lifetimes
Object graph decommissioning
Explicit mapping of interfaces/base classes to concrete types
Type-based resolution
Modular configuration (Installers)
Built-in support for Decorators
Typed Factories
There are probably other features I forgot about...
It appears I was a bit too quick on the trigger here, although to my defense, the Spring.NET documentation also states that there's only XML configuration in the current version.
However, it turns out that if for certain contexts, a very primitive API is available that enables you to configure a context without XML. Here's an example:
var context = new GenericApplicationContext();
context.RegisterObjectDefinition("EggYolk",
new RootObjectDefinition(typeof(EggYolk)));
context.RegisterObjectDefinition("OliveOil",
new RootObjectDefinition(typeof(OliveOil)));
context.RegisterObjectDefinition("Mayonnaise",
new RootObjectDefinition(typeof(Mayonnaise),
AutoWiringMode.AutoDetect));
Notice how this API very closely mirrors the XML configuration schema. Thus, you don't get any fluent API from the IObjectDefinitionRegistry interface, but at least there's an API which is decoupled from XML. Building a fluent API on top of this is at least theoretically possible.
You will find a fully working spring fluent API for spring.net on github:
https://github.com/thenapoleon/Fluent-API-for-Spring.Net
This API brings fluent configuration, and will soon support convention based configuration.
In answer to the first part of your question: the springsource team appears to be working on a code configuration project on github: https://github.com/SpringSource/spring-net-codeconfig. It was announced with (but not included in) the 1.3.1 (december 2010) release.
From the MovieFinder example:
[Configuration]
public class MovieFinderConfiguration
{
[Definition]
public virtual MovieLister MyMovieLister()
{
MovieLister movieLister = new MovieLister();
movieLister.MovieFinder = FileBasedMovieFinder();
return movieLister;
}
[Definition]
public virtual IMovieFinder FileBasedMovieFinder()
{
return new ColonDelimitedMovieFinder(new FileInfo("movies.txt"));
}
}
There is another option using the Spring.AutoRegistration. The same concept used with Unity AutoRegistration.
https://www.nuget.org/packages/Spring.AutoRegistration
http://autoregistration.codeplex.com/
var context = new GenericApplicationContext();
context.Configure()
.IncludeAssembly(x => x.FullName.StartsWith("Company.ApplicationXPTO"))
.Include(x => x.ImplementsITypeName(), Then.Register().UsingSingleton()
.InjectByProperty(If.DecoratedWith<InjectAttribute>))
.ApplyAutoRegistration();
It is also possible to use Spring.FluentContext project.
With it, the configuration of MovieFinder would look as follows:
// Configuration
private static IApplicationContext Configure()
{
var context = new FluentApplicationContext();
context.RegisterDefault<MovieLister>()
.BindProperty(l => l.MovieFinder).ToRegisteredDefaultOf<ColonDelimitedMovieFinder>();
context.RegisterDefault<ColonDelimitedMovieFinder>()
.UseConstructor((FileInfo fileInfo) => new ColonDelimitedMovieFinder(fileInfo))
.BindConstructorArg().ToValue(new FileInfo("movies.txt"));
return context;
}
// Usage
static void Main(string[] args)
{
IApplicationContext context = Configure();
var movieLister = context.GetObject<MovieLister>();
foreach (var movie in movieLister.MoviesDirectedBy("Roberto Benigni"))
Console.WriteLine(movie.Title);
Console.ReadLine();
}
It does not require any hardcoded literal ID for objects (but allows that), it is type safe and contains documentation with samples on GitHub wiki.
Using the Fluent-API-for-Spring.Net, the configuration could look something like:
private void ConfigureMovieFinder()
{
FluentApplicationContext.Clear();
FluentApplicationContext.Register<ColonDelimitedMovieFinder>("ColonDelimitedMovieFinder")
.BindConstructorArgument<FileInfo>().To(new FileInfo("movies.txt"));
// By default, fluent spring will create an identifier (Type.FullName) when using Register<T>()
FluentApplicationContext.Register<MovieLister>()
.Bind(x => x.MovieFinder).To<IMovieFinder>("ColonDelimitedMovieFinder");
}

Resources