-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Runtime endpoint route uris resolving #1098
Comments
@renatorroliveira thank you for bringing this up However, I cant think in a situation where I'd use this in my projects. |
Well, it is very specific indeed. I have several projects that share the same logic of user control and multi tenant implementation. However they are distinct projects and a I can't use these logics as a auth/authz microservice, I must embed them into the project and deploy them on different servers. So, I came with the proposal to isolate that logic into a library/plugin. At this point no problem. The thing is that I want to include the API controllers within the library too. When I was doing that I noticed that there are many approaches for this, none of them is intuitive. The lack of an easy way to register/resolve routes at runtime makes this implementation ugly. I want to include the controllers and dynamically decides if a given route will be included or not in the current application instance based on runtime data. For example, I can have a configuration bean that defines which routes will be included in the internal router: public interface MyRuntimeRoutesConfiguration {
public String getRoutesPrefix();
public boolean isUserControlEnabled();
public boolean isMultiTenantEnabled();
} Then I inject this bean into an override of the path resolver: public interface RuntimeRouteResolver {
String[] getURIsFor(Path pathAnn);
} @Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimePath {
Class<? extends RuntimeRouteResolver> value();
} public class PrefixedRouteResolver implements RuntimeRouteResolver {
private MyRuntimeRoutesConfiguration config;
public PrefixedRouteResolver() {
this.config = CDI.current().select(MyRuntimeRoutesConfiguration.class).get();
}
@Override
public String[] getURIsFor(Path pathAnn) {
String[] uris = pathAnn.value();
for (int i = 0; i < uris.length; i++) {
if (!GeneralUtils.isEmpty(uris[i])) {
uris[i] = this.config.getRoutesPrefix() + uris[i];
}
}
return uris;
}
} @ApplicationScoped
@Specializes
public class RuntimeRouteParser extends PathAnnotationRoutesParser {
private static final Logger LOG = Logger.getLogger(RuntimeRouteParser.class);
/**
* @deprecated CDI eyes only
*/
protected RuntimeRouteParser() {
this(null, null);
}
@Inject
public RuntimeRouteParser(Router router, ReflectionProvider reflectionProvider) {
super(router, reflectionProvider);
}
@Override
protected String[] getURIsFor(Method javaMethod, Class<?> type) {
if (javaMethod.isAnnotationPresent(RuntimePath.class) && javaMethod.isAnnotationPresent(Path.class)) {
Path pathAnn = javaMethod.getAnnotation(Path.class);
RuntimePath runtimePathAnn = javaMethod.getAnnotation(RuntimePath.class);
RuntimeRouteResolver resolve;
String[] uris = new String[] {};
try {
resolve = runtimePathAnn.value().newInstance();
uris = resolve.getURIsFor(pathAnn);
} catch (InstantiationException | IllegalAccessException e) {
LOG.errorf(e, "Error instantiating runtime path resolver.");
checkArgument(false, "Error instantiating runtime path resolver.");
}
checkArgument(uris.length > 0, "You must specify at least one path on @Path at %s", javaMethod);
checkArgument(getUris(javaMethod).length == 0,
"You should specify paths either in @Path(\"/path\") or @Get(\"/path\") (or @Post, @Put, @Delete), not both at %s", javaMethod);
fixURIs(type, uris);
return uris;
}
return super.getURIsFor(javaMethod, type);
}
} This is an initial solution I came up with, but I really believe that this logic could be added to the framework (or something similar) because it enables more flexible approaches for some architectural problems we can face. Of course it is a little specific, but I think flexibility isn't a problem. What do you think? |
This is just an example that adds runtime resolved prefix to the endpoint's URI. Some project that uses the library can specializes the configuration bean and change prefix and/or disable/enable the multi tenant related endpoints for example. I hope this example shows the flexibility this idea brings. |
I was digging into the VRaptor code and I was unable to figure out a way to define the controller's endpoints paths (URI's from the @Path/@Get/@post annotations) at runtime.
In some situations this can be very useful.
I was trying to isolate some common controllers as libraries, but the URI's of those controllers methods must be defined as static strings that must be compilation time resolvable.
Am I missing something here? It is already possible to do that?
I can think of some other situations that this can be useful, like dynamic generation of URI's in multi instance system, some API publication patterns and others.
Do you think this is an interesting feature for VRaptor? If so, I can propose an implementation of this.
The text was updated successfully, but these errors were encountered: