Service Fabric specify fabric url - azure-service-fabric

Is it possible to define which url a service uses instead of the standard fabric:/AppName/ServiceName?
I can't find if this is configurable or not on an application level.

Yes, you can change the name of the service in the ApplicationManifest.xml to something other than the name taken from the service's class name.
Short: just change the name attribute in ApplicationManifest.xml for that service to something else.
In code: If I have this service:
public interface IJustAnotherStatelessService : IService
{
Task<string> SayHelloAsync(string someValue);
}
internal sealed class JustAnotherStatelessService : StatelessService, IJustAnotherStatelessService
{
// Service implementation
}
Registered in Program.cs like this:
ServiceRuntime.RegisterServiceAsync("JustAnotherStatelessServiceType",
context => new JustAnotherStatelessService(context)).GetAwaiter().GetResult();
And in the ServiceManifest.xml for that service
<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest ...>
<ServiceTypes>
<!-- This is the name of your ServiceType.
This name must match the string used in RegisterServiceType call in Program.cs. -->
<StatelessServiceType ServiceTypeName="JustAnotherStatelessServiceType" />
</ServiceTypes>
...
In the ApplicationManifest.xml you will get the suggested name:
<ApplicationManifest ...>
<DefaultServices>
<Service Name="JustAnotherStatelessService">
<StatelessService ServiceTypeName="JustAnotherStatelessServiceType" InstanceCount="[JustAnotherStatelessService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
This will give you an Uri to you service like
fabric:/app_name/JustAnotherStatelessService
Now, go ahead and change the name in the application manifest:
<ApplicationManifest ...>
<DefaultServices>
<Service Name="AwesomeService">
<StatelessService ServiceTypeName="JustAnotherStatelessServiceType" InstanceCount="[JustAnotherStatelessService_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
And your service now answers to
fabric:/app_name/AwesomeService

You can use this uri builder (ServiceUriBuilder.cs) class from here: https://github.com/Azure-Samples/service-fabric-dotnet-web-reference-app/blob/master/ReferenceApp/Common/ServiceUriBuilder.cs
For stateless service you can easily get the proxy:
var serviceUri = new ServiceUriBuilder(ServiceName);
var proxyFactory = new ServiceProxyFactory();
var svc = proxyFactory.CreateServiceProxy<IServiceName>(serviceUri.ToUri());
For stateful service you have to specify the partition.
var serviceUri = new ServiceUriBuilder(StatefulServiceName);
var proxyFactory = new ServiceProxyFactory();
//this is just a sample of partition 1 if you are using number partitioning.
var partition = new ServicePartitionKey(1);
var svc = proxyFactory.CreateServiceProxy<IStatefulServiceName>(serviceUri.ToUri(), partition);

Related

Configuring Keycloak provider with SPI

I am trying to configure one of my providers factory (its ID is "phone-verification") with the following code :
#Override
public void init(Config.Scope config) {
String lifespan = config.get("lifespan");
logger.warn("Lifespan : " + lifespan);
}
And I have my configuration done in standalone.xml with the following property :
<spi name="phoneVerification">
<default-provider>phone-verification</default-provider>
<provider name="phone-verification" enabled="true">
<properties>
<property name="lifespan" value="2592000"/>
</properties>
</provider>
</spi
However config.get("lifespan") always returns null. Is there any extra step or am I doing anything wrong ?
NOTE : I specified the config file with the /keycloak/bin/standalone.sh --server-config=standalone.xml.
Hi I had the same problem and I solved it by replacing the name attribute of spi tag by the name of an SPI type. There is so many SPI types inside Keycloak.
For exemple if your provide is implementing Authenticator SPI you should configure your provider like this:
<spi name="authenticator">
<provider name="Basic-Authenticator" enabled="true">
<properties>
<property name="user" value="testUser"/>
</properties>
</provider>
</spi>
Same If you are implementing a requered action SPI:
<spi name="required-action">
<provider name="Basic-Migration" enabled="true">
<properties>
<property name="action" value="login"/>
</properties>
</provider>
</spi>
Then just use properties in your factory class like:
#Override
public void init(Scope config) {
String username = config.get("user");
LOG.info("This is the provider property: " + username);
}
Don't forget that inside provider tag, the name attribute is the Id of provider in the provider factory class.

Mono WCF Rest Service With Multiple Contracts "no endpoints are defined in the configuration file"

I want to host a WCF Rest Service with multiple contracts via mono each implemented in a separate partial class. I read many posts on similar issues, yet there was no solution for mono. I incorporated or at least tested all suggestions I could find and by now my code looks a lot like other solutions, yet does not work.
The application runs successfully on my local machine but throws an error once I deploy it via mono.
Service 'MyWebServiceEndpoint' implements multiple ServiceContract types, and no endpoints are defined in the configuration file.
Here is one of the endpoints with the contract. All the others are very much like this one. They all are a partial class MyWebServiceEndpoint implementing another contract.
namespace MyServer.MyEndPoints {
public partial class MyWebServiceEndpoint : INotificationEndpoint {
public string GetNotifications(int limit) {
// Do stuff
}
}
[ServiceContract]
public interface INotificationEndpoint {
[OperationContract]
[WebGet]
string GetNotifications(int limit);
}
}
My App.config looks like this. I removed the IP and port, as they are the server address.
<system.serviceModel>
<services>
<service name="MyServer.MyEndPoints.MyWebServiceEndpoint" behaviorConfiguration="WebService.EndPoint">
<host>
<baseAddresses>
<add baseAddress="http://ip:port>"/>
</baseAddresses>
</host>
<endpoint address="/message"
binding="webHttpBinding"
contract="MyServer.MyEndPoints.IMessageEndpoint"
behaviorConfiguration="WebBehavior"/>
<endpoint address="/music"
binding="webHttpBinding"
contract="MyServer.MyEndPoints.IMusicEndpoint"
behaviorConfiguration="WebBehavior"/>
<endpoint address="/notification"
binding="webHttpBinding"
contract="MyServer.MyEndPoints.INotificationEndpoint"
behaviorConfiguration="WebBehavior"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WebService.EndPoint">
<serviceMetadata httpGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
I open the service in C# like this.
WebServiceHost = new WebServiceHost(typeof(MyWebServiceEndpoint));
WebServiceHost.Open();
The Error message I receive on mono is:
Unhandled Exception:
System.InvalidOperationException: Service 'MyWebServiceEndpoint' implements multiple ServiceContract
types, and no endpoints are defined in the configuration file. WebServiceHost can set up default
endpoints, but only if the service implements only a single ServiceContract. Either change the
service to only implement a single ServiceContract, or else define endpoints for the service
explicitly in the configuration file. When more than one contract is implemented, must add base
address endpoint manually
I hope you have some hints or someone knows how to solve the issue. Thank you already for reading up to here.
I am not familiar with Mono, Does the Mono support Webconfig file? I advise you to add the service endpoint programmatically.
class Program
{
/// <param name="args"></param>
static void Main(string[] args)
{
WebHttpBinding binding = new WebHttpBinding();
Uri uri = new Uri("http://localhost:21011");
using (WebServiceHost sh = new WebServiceHost(typeof(TestService),uri))
{
sh.AddServiceEndpoint(typeof(ITestService), binding, "service1");
sh.AddServiceEndpoint(typeof(IService), binding, "service2");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true
};
sh.Description.Behaviors.Add(smb);
}
sh.Opened += delegate
{
Console.WriteLine("service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("service is closed");
};
sh.Open();
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebGet]
string GetData(int id);
}
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet]
string Test();
}
public class TestService : ITestService,IService
{
public string GetData(int id)
{
return $"{id},";
}
public string Test()
{
return "Hello " + DateTime.Now.ToString();
}
}
Result.
According to the official documentation, we had better not use Partial class.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/multiple-contracts
Besides, we could consider launching multiple service host for every service implemented class.
Feel free to let me know if the problem still exists.

Creating a admin controller using adminhtml id

I'm trying to add a controller accessible on admin menu through url:
https://dev.m2t2.com/admin_k1tgag/admin/helloWorld/index/key/0195fab99cc865bb756a77e8fe5ceedb6f8eee97de91d569398d383cef4f0d81/
Generated by the XML code inserted below. But it keeps returning
Invalid security or form key. Please refresh the page.
Router.xml :
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="adminhtml">
<module name="Study_Admin" before="Magento_Backend"/>
</route>
</router>
</config>
In menu i inserted:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
<menu>
<add id="Study_Admin::greetings" title="Greetings" translate="title" module="Study_Admin" parent="Magento_Backend::content" sortOrder="50" dependsOnModule="Study_Admin" resource="Study_Admin::greetings"/>
<add id="Study_Admin::greetings_helloworld" title="Hello World" translate="title" module="Study_Admin" parent="Study_Admin::greetings" sortOrder="10" dependsOnModule="Study_Admin" action="adminhtml/helloWorld" resource="Study_Admin::greetings"/>
</menu>
</config>
But when i access the controller through the menu i have no success. I started debugging and i checked that non-custom controllers extends \Magento\Backend\App\Action class to pass validations inside magento routing core flow. I did the same but i still have no success.
Below my controller class:
<?php
namespace Study\Controller\Adminhtml\HelloWorld;
use Magento\Framework\App\Action\HttpGetActionInterface as HttpGetActionInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
use Magento\Backend\App\Action\Context;
use ‌Magento\Framework\App\ActionInterface;
class Index extends \Magento\Backend\App\Action
{
const MENU_Id = "Study_Admin::greetings_helloworld";
protected $resultPageFActory;
public function __construct(Context $context, PageFactory $resultPageFActory)
{
parent::__construct($context);
$this->resultPageFActory = $resultPageFActory;
}
public function execute()
{
$resultPage = $this->resultPageFActory->create();
$resultPage->setActiveMenu(static::MENU_Id);
$resultPage->getConfig()->getTitle()->prepend(__('Hello World'));
return $resultPage;
// TODO: Implement execute() method.
}
}
The file structure is :
Thanx in advance, and take care.
It works... was just my namespace in Controller's class that had an error
'namespace Study\Admin\Controller\Adminhtml\Helloworld;'

Apache camel cxfrs—Can't find the request for <URL> Observer

I tried to develop a rest service and expose the same via Apache Camel's CXFRS. I followed all the steps given in http://camel.apache.org/cxfrs.html and also referred to many samples given. I already referred to the question Can't find the the request for url Observer, but in my case it is a simple rest request. Below are the Service class, Route class, and cxf context used:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:cxf="http://camel.apache.org/schema/cxf" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<context:annotation-config />
<!-- enable Spring #Component scan -->
<context:component-scan base-package="org.camelsample.rest" />
<cxf:rsServer id="rsServer" address="/rest"
serviceClass="org.camelsample.rest.service.SampleRestService"
loggingFeatureEnabled="true" loggingSizeLimit="20">
<cxf:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</cxf:providers>
</cxf:rsServer>
<camel:camelContext id="samplerestservice"
xmlns="http://camel.apache.org/schema/spring">
<contextScan />
<jmxAgent id="agent" createConnector="true" />
</camel:camelContext>
</beans>
The Service Class:
package org.camelsample.rest.service;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
public class SampleRestService {
#GET
#Path("/")
public String sampleService() {
return null;
}
}
The Route Class:
package org.camelsample.rest.route;
import org.apache.camel.spring.SpringRouteBuilder;
public class SampleRestRoute extends SpringRouteBuilder {
#Override
public void configure() throws Exception {
// TODO Auto-generated method stub
from("cxfrs:bean:rsServer").log("Into Sample Route").setBody(constant("Success"));
}
}
But when I try to hit and test using http://localhost:8080/rest, I always get the following error message:
2015-05-29 13:38:37.920 WARN 6744 --- [nio-8080-exec-2] o.a.c.t.servlet.ServletController : Can't find the the request for http://localhost:8080/favicon.ico's Observer
2015-05-29 13:38:40.295 WARN 6744 --- [nio-8080-exec-3] o.a.c.t.servlet.ServletController : Can't find the the request for http://localhost:8080/rest's Observer
Am using Spring boot to test the rest sample.
Does it work with this URL instead ?
http://localhost:8181/cxf/rest
If you just use address="/rest" as your address then you will probably get the default Jetty port 8181 and default CXF servlet path /cxf as the base URL.
If you specifically want to use the URL you have given then try this instead:
address="http://0.0.0.0:8080/rest"

Symfony DIC and Parent Services not working

I'm integrating Symfony DIC in a zend framework application, that's going fine except for parent services.
In my DIC config I have a parent service PC_Service which will be extended by all my services.
The problem is that the entity manager is not available (NULL) in the services that extend PC_Service. When I inject the entitymanager via service.stats the entitymanger is set correctly.
...
<service id="pc.service" class="PC_Service" abstract="true">
<call method="setEntityManager">
<argument type="service" id="doctrine.entitymanager" />
</call>
</service>
...
<service id="service.stats" class="Application_Service_Stats" parent="pc.service" />
...
PC_Service
abstract class PC_Service
{
protected $_em;
public function setEntityManager($entityManager)
{
$this->_em = $entityManager;
}
}
Application_Service_Stats
class Application_Service_Stats extends PC_Service
{
... $this->_em should be set here.
}
I hope someone can tell me what I'm doing wrong.
Don't know if it's a typo but it should be doctrine.orm.default_entity_manager or doctrine.orm.entity_manager (alias of the previuos):
<service id="pc.service" class="PC_Service" abstract="true">
<call method="setEntityManager">
<argument type="service" id="doctrine.orm.default_entity_manager" />
</call>
</service>
The solution is to compile the service container near the end of the ZF bootstrap. This process has a step called ResolveDefinitionTemplatesPass which patches in the calls from parent services.
This is typically done by the Symfony Kernel, but of course it isn't present in a ZF integration.
protected function _initServiceContainerCompilation()
{
// Wait for the SC to get built
$this->bootstrap('Services');
// Doctrine modifies the SC, so we need to wait for it also
$this->bootstrap('Doctrine');
// Compiling the SC allows "ResolveDefinitionTemplatesPass" to run,
// allowing services to inherit method calls from parents
$sc = $this->getResource('Services');
$sc->compile();
}