akka-camel: setting URI endpoint in application.conf? - apache-camel

I have an Akka actor that extends camel's UntypedConsumerActor. I want to provide the value of its endpoint URI in application.conf instead of hard-coding, since the URI will be different in Dev, Test, and Production environment. I like to do this with pure typesafe config and don't have to bother with wiring in Spring. A sample application.conf would be great.

You can read config property from the UntypedConsumerActor with something like:
this.uri = getContext().system().settings().config().getString("myendpoint-uri");
and in your application.conf define:
myendpoint-uri = "mina2:tcp://localhost:6200?textline=true"

Related

How can you configure the ObjectMapper used by AppEngine

I have a AppEngine project that is served using Google Cloud EndPoints.
Some of the Request and Response objects (which I have no control over) have no attributes.
When those endpoints are invoked the call will fail with:
com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler handle: exception occurred while invoking backend method
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class au.com.xandar.wylas.licence.endpoint.response.SendUserInviteResponse and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
Normally I would just get the ObjectMapper on instance startup and call
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
But I am struggling to work out how to get hold of the ObjectMapper that AppEngine is using.
And note:
I am not using Spring
I am not using Guice
I do not want to introduce either of these frameworks into the mix.
How can can I retrieve the ObjectMapper that AppEngine is using so that I can modify it's config?

How to use camel consul component for agent API?

As per camel documentation for consul(camel.apache.org/consul-component.html), the supported HTTP API are kv, event and agent. There are example of kv (key/value store) which are working fine but there is no such example for agent API. I went thruogh the documentation of Consul [www.consul.io/docs/agent/http/agent.html] and the corresponding java client [github.com/OrbitzWorldwide/consul-client] as well and tried to figure out how consul:agent component should work but I have found nothing simple there.
main.getCamelTemplate().sendBodyAndHeader(
"consul:agent?url=http://localhost:8500/v1/agent/service/register",
payload,
ConsulConstants.CONSUL_ACTION, ConsulAgentActions.AGENT); //also tried with ConsulAgentActions.SERVICES, but no luck
I also checked the test cases mention at https://github.com/apache/camel/tree/master/components/camel-consul/src/test/java/org/apache/camel/component/consul but unable to find anything related to agent api.
So my question is that how to use consul:agent component.
UPDATE: I tried the below code and able to get the services.
Object res = main.getCamelTemplate().requestBodyAndHeader("consul:agent", "", ConsulConstants.CONSUL_ACTION, ConsulAgentActions.SERVICES);
It seems that the consul component only work for the GET operation of the HTTP agent API. But in that case how do I register a new service (like /v1/agent/service/register : Registers a new local service) with consul component?
This code works for me:
ImmutableService service =
ImmutableService.builder()
.id("service-1")
.service("service")
.addTags("camel", "service-call")
.address("127.0.0.1")
.port(9011)
.build();
ImmutableCatalogRegistration registration =
ImmutableCatalogRegistration.builder()
.datacenter("dc1")
.node("node1")
.address("127.0.0.1")
.service(service)
.build();
ProducerTemplate template = main.getCamelTemplate();
Object res = template.requestBodyAndHeader("consul:catalog", registration, ConsulConstants.CONSUL_ACTION, ConsulCatalogActions.REGISTER);
But it's looking some inelegantly (like workaround), and i think there are other solutions.
One can use
.to("consul:agent?action=SERVICES")
to retrieve the registered Services as Map<String, Service>, with service id as map key.
And
.to("consul:catalog?action=REGISTER")
to write registrations, expecting an ImmutableCatalogRegistration as body
Note that you can employ a CamelServiceRegistrationRoutePolicy to register Camel routes as services automatically.

Intercepting cxf web service header with Apache Camel (Java DSL)

I created a web service client to handle cxf soap web services with apache camel.
String serviceUri = "cxf:http://localhost:10000/myservice?serviceClass=" +
MyRequest.class.getCanonicalName();
from(uri).to("mock:xyz");
The web service receives the soap call but throws an exception since the request requires a handling for wss.
org.apache.cxf.binding.soap.SoapFault: MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.
The reason is, that the service requires ws security, which can be seen by lloking at the request.
<SOAP-ENV:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
I found out that I need to implement an interceptor to handle header properties.
My questions:
How can I add an interceptor to handle the header attributes with Camel Java-DSL?
Will this be sufficient to get rid of the SOAP Fault?
You can do it through
cxfEndpointConfigurer option #see: Camel-CXF configuration
(I use Spring (it is much easier)), but I guess for DSL URI will look like:
String serviceUri = "cxf:http://localhost:10000/myservice?serviceClass=" +
MyRequest.class.getCanonicalName() +
"&cxfEndpointConfigurer="+ MyConfigurer.class.getCanonicalName();
by implementing org.apache.camel.component.cxf.CxfEndpointConfigurer you have ability to add an Interceptor inside configureServer method
server.getEndpoint().getInInterceptors().add(new MyJAASLoginInterceptor());
if you run your Camel in container with JAAS (like JBOSS) you can use extension from
org.apache.cxf.interceptor.security.JAASLoginInterceptor
with needed callback handler.
Simple example which validates user/password from WSS header against JBOSS users:
public class MyJAASLoginInterceptor extends javax.security.auth.callback.JAASLoginInterceptor {
#Override
protected CallbackHandler getCallbackHandler(String name, String password) {
return new org.apache.cxf.interceptor.security.NamePasswordCallbackHandler(name, password, "setCredential");
}
}

How to access config/env/all.js data in a client controller?

I have some configuration values(numbers) that I need while doing some computation in the angular code in the client controller. I general, how can one access the serverside config data in the clientside code?
If note is it possible to have a config file/folder in the public folder and easily access using angular code in client controller?
I'm not 100% sure what you are looking for here, but you have basically 3 options to handle this.
Expose An API Endpoint
You should be able to simply create an API endpoint to read the config data on the server and send it down to the client as JSON. Then you could access it in Angular like so:
$http.get('/api/config')
.success(function(configData){
//Do something with config data
});
Expose Config File Publicly
Warning - This may not be wise if your config contains sensitive data such as connection strings.
If you have a .json or a .xml file on the server with this info, then you could just make it available to HTTP GET requests and then the same code as above would apply. With the exception that if it is XML you will need to add a transform to parse the data.
$http.get('/config.json')
.success(function(configData){
//Do something with config data
});
Embed Config As Angular Constant/Value
Note - This won't work if your data is dynamic on the server.
An even simpler way is to simply put your configuration into a .js file and register it with Angular as a constant or a value.
angular.module('myModule')
.constant('config', {
foo:'bar',
blah:123
});
This way you can simply inject that anywhere in your app that you need access to it.

Cloud Endpoints HTTP Cookies

I am implementing Cloud Endpoints with a Python app that uses custom authentication (GAE Sessions) instead of Google Accounts. I need to authenticate the requests coming from the Javascript client, so I would like to have access to the cookie information.
Reading this other question leads me to believe that it is possible, but perhaps not documented. I'm not familiar with the Java side of App Engine, so I'm not quite sure how to translate that snippet into Python. Here is an example of one of my methods:
class EndpointsAPI(remote.Service):
#endpoints.method(Query_In, Donations_Out, path='get/donations',
http_method='GET', name='get.donations')
def get_donations(self, req):
#Authenticate request via cookie
where Query_In and Donations_Out are both ProtoRPC messages (messages.Message). The parameter req in the function is just an instance of Query_In and I didn't find any properties related to HTTP data, however I could be wrong.
First, I would encourage you to try to use OAuth 2.0 from your client as is done in the Tic Tac Toe sample.
Cookies are sent to the server in the Cookie Header and these values are typically set in the WSGI environment with the keys 'HTTP_...' where ... corresponds to the header name:
http = {key: value for key, value in os.environ.iteritems()
if key.lower().startswith('http')}
For cookies, os.getenv('HTTP_COOKIE') will give you the header value you seek. Unfortunately, this doesn't get passed along through Google's API Infrastructure by default.
UPDATE: This has been enabled for Python applications as of version 1.8.0. To send cookies through, specify the following:
from google.appengine.ext.endpoints import api_config
AUTH_CONFIG = api_config.ApiAuth(allow_cookie_auth=True)
#endpoints.api(name='myapi', version='v1', auth=AUTH_CONFIG, ...)
class MyApi(remote.service):
...
This is a (not necessarily comprehensive list) of headers that make it through:
HTTP_AUTHORIZATION
HTTP_REFERER
HTTP_X_APPENGINE_COUNTRY
HTTP_X_APPENGINE_CITYLATLONG
HTTP_ORIGIN
HTTP_ACCEPT_CHARSET
HTTP_ORIGINALMETHOD
HTTP_X_APPENGINE_REGION
HTTP_X_ORIGIN
HTTP_X_REFERER
HTTP_X_JAVASCRIPT_USER_AGENT
HTTP_METHOD
HTTP_HOST
HTTP_CONTENT_TYPE
HTTP_CONTENT_LENGTH
HTTP_X_APPENGINE_PEER
HTTP_ACCEPT
HTTP_USER_AGENT
HTTP_X_APPENGINE_CITY
HTTP_X_CLIENTDETAILS
HTTP_ACCEPT_LANGUAGE
For the Java people who land here. You need to add the following annotation in order to use cookies in endpoints:
#Api(auth = #ApiAuth(allowCookieAuth = AnnotationBoolean.TRUE))
source
(Without that it will work on the local dev server but not on the real GAE instance.)

Resources