// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= Java Services Execution from Ignite.NT

== Overview

Ignite.NET can work with Java services the same way as with .NET services. To call a Java service from a .NET application,
you need to know the interface of the service.

== Example

Let's review how to use this capability by taking a usage example.

=== Create Java Service

[tabs]
--
tab:Java[]
[source,java]
----
public class MyJavaService implements Service {
  // Service method to be called from .NET
  public String testToUpper(String x) {
    return x.toUpperCase();
  }

  // Service interface implementation
  @Override public void cancel(ServiceContext context) { // No-op.  }
  @Override public void init(ServiceContext context) throws Exception { // No-op. }
  @Override public void execute(ServiceContext context) throws Exception { // No-op. }
}
----
--

This Java service can be deployed on any nodes (.NET, C{pp}, Java-only), so there are no restrictions on deployment options:

[tabs]
--
tab:Java[]
[source,java]
----
ignite.services().deployClusterSingleton("myJavaSvc", new MyJavaService());
----
--

=== Call Java Service From .NET

Create a version of the service interface for .NET:

[tabs]
--
tab:C#[]
[source,csharp]
----
// Interface can have any name
interface IJavaService
{
  // Method must have the same name (case-sensitive) and same signature:
  // argument types and order.
  // Argument names and return type do not matter.
  string testToUpper(string str);
}
----
--

Get the service proxy and invoke the method:

[tabs]
--
tab:C#[]
[source,csharp]
----
var config = new IgniteConfiguration
{
  // Make sure that Java service class is in classpath on all nodes, including .NET
  JvmClasspath = @"c:\my-project\src\Java\target\classes\"
}

var ignite = Ignition.Start(config);

// Make sure to use the same service name as in deployment
var prx = ignite.GetServices().GetServiceProxy<IJavaService>("myJavaSvc");
string result = prx.testToUpper("invoking Java service...");
Console.WriteLine(result);
----
--

== Interface Methods Mapping

The .NET service interface is mapped to its Java counterpart dynamically. This happens at the time of the method invocation:

* It is not necessary to specify all Java service methods in the .NET interface.
* The .NET interface can have members that are not present in Java service. You won't get any exception until you call these missing methods.

The Java methods are resolved the following way:

* Ignite looks for a method with the specified name and parameter count. If there is only one exist, Ignite will use it.
* Among the matched methods Ignite looks for a method with compatible arguments (via `Class.isAssignableFrom`).
Ignite invoke the matched method or throws an exception in case of ambiguity.
* The method return type is ignored, since .NET and Java do not allow identical methods with different return types.

See link:net-specific/platform-interoperability[Platform Interoperability, Type Compatibility section] for details on
method arguments and result mapping. Note, that the `params/varargs` are also supported, since in .NET and Java these are
syntactic sugar for object arrays.
