AppDynamics to group REST endpoints containing UUIDs as a single business transaction - java

I have a web application running on JBoss/Wildfly and using RESTEasy. I'm monitoring it with AppDynamics. I've configured my business transaction detection to use a Java Servlet.
This just about works, but some of my REST paths contain UUIDs, for example:
/data/scenario/d345d238-e0d2-4e01-a96e-4bf11290ce1d/job
Each time this end-point is invoked with a different UUID, AppD treats it as a different business transaction. Is there a way to make AppD recognise UUIDs within a path, and group these into a single business transaction? Something like:
/data/scenario/{id}/job
I should be able to do it by applying a regex to the request's path info:
request.getPathInfo().replaceAll(
"[0-9a-f]{8}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{4}\\-[0-9a-f]{12}",
"{id}")
or even just
request.getPathInfo().replaceAll("[0-9a-f\\-]{36}", "{id}")
but I can't figure out how to escape it properly.
${getPathInfo().replaceAll([0-9a-f\\-]{36}, id)}
doesn't work, and neither does
${getPathInfo().replaceAll(\[0\-9a\-f\\\\-\]\{36\}, id)}

Configuration->Instrumentation->Transaction Detection->Add
On the "Split Transactions Using Request Data" section you must choose "Specific URI Segments"
Segment Numbers: 1,2,4
In your case transaction name will be "/data/scenario/job"
Sample Configuration:

Related

Keycloak - how to handle multiple work contexts

I have an application where single user can work in contexts of multiple companies. We call such a connection (user<->company) a permit. Every one of this permits can have different sets of permissions/roles. We want user to login just once and then he can simply change permits within application without need to enter password again.
Till now we had only one application and kept this whole permission model in our own DB. Unfortunately now we have to support second application which should inherit those permits. I was wondering wether is possible to move that model to keycloak so we don't have to replicate it to every single db and keep it in sync manually.
I have searched keycloak documentation regarding this topic but have found no information att all, which seems quite odd, because I don't think we are the first one working with multiple context application.
So now I'm asking is it possible to configure our model in keycloak and if so, how to do it? Eventually are there different options? I guess that I can provided that model as a claim with json structure but that doesn't feel right to me. I was thinking about custom IDP which could provide such claims based on DB so there no spelling errors and less repetition but I feel there should be a better way.
You could try to write your own Keycloak provider (SPI). There is a built in mechanism that allows you to expose REST endpoint on the Keycloak: https://github.com/keycloak/keycloak/tree/master/examples/providers/domain-extension
That REST could be called with authorized context only for example by passing Access-Token (Authorization header with Bearer value). On the provider level (through implementation of: org.keycloak.services.resource.RealmResourceProviderFactory and org.keycloak.services.resource.RealmResourceProvider) you have access to user's Keycloak session and object UserModel like in the following code:
AuthenticationManager.AuthResult authResult = new AppAuthManager().authenticateBearerToken(keycloakSession, keycloakSession.getContext().getRealm());
UserModel userModel = authResult.getUser();
UserModel class has methods for getting and setting attributes, so some information that indicates the current permit/company ID can be stored there. You can use REST methods exposed on the Keycloak to modify the model within the 'session' (represented by Access-Token).
The Github example shows also how to use another Keycloak provider (ex. built-in JPA provider) from you custom provider's level, so using that approach you could try to connect to the database with your permits/company informations. Of course the datasource representing you database should also be registered as Keycloak datasource.

Enabling Hibernate filters inside a servlet filter in Spring

I am working on a multi-tenant application which means I need to be able to filter API responses based on the organization account that owns the requesting user profile. In our model, this is referred to as a Tenant. I have working Hibernate filters in place which let me control the scope of my resulting queries so that a user under tenantId of "foo" will only see rows in associated models which are also owned by foo.
The challenge I have is that I am having to enable this filter from within the scope of a controller method - and so am putting the code at touch-points within the associated model services. This seems like a candidate for a Servlet filter but that does not seem to work.
To implement, I added a public enableFilter method to an #Transactional service which uses its internal repository reference to enable the filter against my Hibernate session. I then #Autowired this into my servlet filter so I can pickup the tenant associated for the currently requesting user and enable the Hibernate filter accordingly.
The problem is, this doesn't work. It seems that the Hibernate session is either not active or is reset before the actual service does any work. The ressulting queries with the servlet filter enabled do not include my tenant filtering. Enabling those filters within my services does so I know the filters themselves are correct. Is there something I am missing or am I going to have to enable these filters further up the food chain of my request processing?

jetty AsyncProxyServlet/AsyncMiddleManServlet

I am planning to use one of the above servlets. My use case is, client hits one of the server [This is where I would be using Proxy or MiddleMan servlet]. From here I would like to talk to other services based on the request URL. Can I use these servlets for this use case
example:
client -->http://<headend>/service1/x/y ---In MiddleManServlet -- http://server1/service1/x/y
client -->http://<headend>/service2/x/y ---In MiddleManServlet -- http://server2/service2/x/y
Can this be accomplished using this servlets?. I know I have to override rewriteTarget method.
Yes, this can be accomplished using something like Jetty's AsyncProxyServlet. You would basically need to set up your app container to pass requests with a certain path to your servlet ("service1" for example) and then in your servlet you would validate if the path the user was trying to hit was valid or whether it is an error (i.e. you probably don't want people proxying through your app to random services).
http://download.eclipse.org/jetty/9.3.11.v20160721/apidocs/org/eclipse/jetty/proxy/ProxyServlet.Transparent.html

Check Camel config at load-time?

We're using Spring Boot for an application, with Camel for routing. We split most routes with an endpoint "URI" String, mainly for testability's sake:
rest("/foo").post().to("direct:foo");
from("direct:foo").process(exchange -> {
exchange.getIn().setBody(service.doStuff());
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, CONTENT_TYPE_JSON);
});
However if we mis-type one of the "direct:foo" strings, we don't get an error until the route is invoked. I'd like to be able to get the error earlier, as part of the application's startup process.
Obviously using static finals instead of String literals will keep us from mis-typing an individual endpoint value, but it won't help with the situation where one endpoint doesn't go anywhere, or we're using one for a from without sending anything to it.
Is there a way I can ask Camel to verify all routes have working to/from endpoints, once Spring has finished scanning the classpath and building beans?

Spring Framework HttpRequestHandler failure

We have an application which communicates via REST requests made by clients.
The REST requests contain "region name" and a "ID" as parameters
So, a request would look something like this (for a DELETE)
http://host:port/regionnameID
These REST requests between regions in a federation are properly URL encoded
I find that these request fail if the region name has a slash ("/") in it.
Then, the request would look like so
http://host:port/region/nameID
This is due to incorrect interpretation of the Rest URL by HttpRequesthandler when there is a '/' in the region name.
Now, we have no control over clients sending REST request with "/" in the Region name.
Is there any method / configuration / workaround that can be done to prevent the HttpRequestHandler from returning 404
you should rewrite your urls with urlrwrite and use query parameters internal.
<rule>
<name>Inbound:</name>
<from>^(.*)ID$</from>
<to last="true">delete?regionName=$1</to>
</rule>
Add your urlrewrite Filter in front of all other filters in web.xml
This is a bit of a dirty problem. What I would try to do here is to use the Spring #RequestMapping annotation. There is some documentation on it here:
http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html
You can specific ant wildcards in the value you pass #RequestMapping. If you have a limited number of regions, then you can map them all to a single method as follows:
#RequestMapping(value={"/region1**","/region2**","/region3**")
In your controller method, you will have to add additional logical for parsing out the nameID.
If you have a large number of regions, I would then create a separate Spring Web app (servlet) just to handle these requests. That app would have a cached lookup table of regions.
Configure your own handlerMapping bean (perhaps based on AbstractUrlHandlerMapping)

Categories