I extended JDBC adapter and used a model.json configuration custom schema factory with 1 original schema and 2 derived schemas to add rules and that worked, rules got executed on original schema during planning, but their end-result didn't get chosen as the best option by the Volcano planner because it's too expensive. Rules transformed RelNode to execute on 2 derived schemas. More details below and in code.
1) Can I tell Volcano planner to ignore 1 out of 3 schemas that I passed through custom JDBC SchemaFactory?
I want the parser to work on that 1 original schema, but for the planner to never suggest an optimal (cheapest) plan in that schema (only other 2 derived schemas). 1 original schema is always mapped 1-to-1 with other 2 derived schemas, so the RelNode that my rule returns is always semantically equivalent, just more expensive (security reasons).
2) If that can't work, how can I call HepPlanner instead of default Volcano planner from SchemaFactory that is set in model.json, since that's my starting point?
You can find my entire code on GitHub, I made it publicly available so that everyone can have a better starting point with Calcite than I did.
Here is the link: https://github.com/igrgurina/multicloud_rewriter
Calcite library is amazing, but it's really hard to get into because it lacks examples and tutorials for common tasks.
Ideally, I would have HepPlanner execute my rules that transform them to semantically equivalent expressions that use 2 derived schemas instead of 1 original schema (I have a rule that does that), and then have Volcano planner optimize that using only 2 derived schemas, without having an idea that 1 original schema exists, due to security reasons.
I haven't found any reasonable examples that demonstrate how to do that so any help would be appreciated (please don't post links to Druid example, or Apache Calcite docs website, I went through them a thousand times).
I've managed to make this work by using Hook.PROGRAM and prepending my custom program that executes my rules before all others.
Since Hook is marked as for testing and debugging only in Calcite library, I would say this is not how it's supposed to be done, but I have nothing better at the moment.
Here is a short summary with code sample:
public static class MultiCloudHookManager {
private static final Program PROGRAM = new MultiCloudProgram();
private static Hook.Closeable globalProgramClosable;
public static void addHook() {
if (globalProgramClosable == null) {
globalProgramClosable = Hook.PROGRAM.add(program());
}
}
private static Consumer<Holder<Program>> program() {
return prepend(PROGRAM);
}
// this doesn't have to be in the separate program
private static Consumer<Holder<Program>> prepend(Program program) {
return (holder) -> {
if (holder == null) {
throw new IllegalStateException("No program holder");
}
Program chain = holder.get();
if (chain == null) {
chain = Programs.standard();
}
holder.set(Programs.sequence(program, chain));
};
}
}
The MultiCloudHookManager is then used in SchemaFactory, where you simply call MultiCloudHookManager.addHook() method. In this case, MultiCloudHookManager.PROGRAM is set to MultiCloudProgram, that simply executes a set of rules in HepPlanner.
For full details, refer to the source code in GitHub repository.
This hack solution is inspired by another library.
Related
Suppose I have an aggregate that, for some operation, requires the existence of another aggregate. Let's assume I have a car and a garage. There might be a command called ParkInGarage that looks like this:
public class ParkInGarage {
#TargetAggregateIdentifier
public final UUID carId;
public final Garage garage;
//... constructor omitted
}
I've read that to validate the existence of an aggregate, it is good practice to use the loaded aggregate in commands since that already implies its existence (as opposed to passing a garageId).
Now when unit-testing the Car using Axon's fixtures, I can not simply instantiate my Garage by saying new Garage(buildGarageCmd). It will say:
java.lang.IllegalStateException: Cannot request current Scope if none is active
Because no infrastructure was set up.
How would I test such a case, or should I design the aggregate differently?
Abstracted, real-world example
The aggregate root I am working with may have a reference to itself to form a tree-structure of said aggregate root. Let's call it Node.
#Aggregate
public class Node {
private Node parentNode;
}
Upon creation, I can pass an Optional<Node> as parent, or set the parent at a later time using a separate command. Whether the parent should be defined as instance or by ID is part of the question.
public class AttachNodeCmd {
#TargetAggregateIdentifier
public final UUID nodeId;
public final Optional<Node> parentNode;
}
In the command handler, I need to check if attaching the node to given parent would introduce a cycle (the structure is supposed to be a tree, not a common graph).
#CommandHandler
public Node(AttachNodeCmd command) {
if (command.parentNode.isPresent()) {
Node currentNode = command.parentNode.get();
while (currentNode != null) {
if (currentNode.equals(this)) throw new RecursionException();
currentNode = currentNode.parentNode.orElse(null);
}
}
//Accept the command by applying() an Event
}
At some point, the parent needs to be instantiated to perform those checks. This could either be done by supplying the aggregate instance in the command (discouraged), or by supplying a Repository<Node> and the nodeId to the command handler, which is the aggregate itself and also discouraged. Currently I don't see a right way to do this and further down the road a way to test it.
I wouldn't put AR instances in commands. Command schemas should be stable and easy to serialize/reserialize as they are message contracts.
What you could do instead is resolving the dependency in the command handler.
//ParkInGarage command handler
Garage garage = garageRepository.garageOfId(command.garageId);
Car car = carRepository.carOfId(command.carId);
car.parkIn(garage);
I don't know Axon Framework at all, but that should be relatively easy to test now.
I think #plalx is putting you on the right track. Commands are part of your API/Message Contract and exposing the Aggregate in there isn't that great an idea.
Additionally I'd like to note that the AggregateFixtures in Axon are there to test a single Aggregate, not the coordination of operations between Aggregates.
Coordination between aggregates/bounded contexts is typically where you see sagas coming in to play. Now to be honest, I am a bit in doubt whether this use case justifies a Saga, but I could imagine that if the ParkCarInGarageCommand fails because the Garage Aggregate is full (for example), that you need to instruct the Car Aggregate through another command telling it it's a no-go. The Saga set up in Axon might help you with this as you can easily catch (1) the exception from handling the command or (2) handle the event notifying the operation wasn't successful.
Let me elaborate on the title:
I want to implement a system that would allow me to enable/disable/modify the general behavior of my program. Here are some examples:
I could switch off and on logging
I could change if my graphing program should use floating or pixel coordinates
I could change if my calculations should be based upon some method or some other method
I could enable/disable certain aspects like maybe a extension api
I could enable/disable some basic integrated profiler (if I had one)
These are some made-up examples.
Now I want to know what the most common solution for this sort of thing is.
I could imagine this working with some sort of singelton class that gets instanced globally or in some other globally available object. Another thing that would be possible would be just constexpr or other variables floating around in a namespace, again globally.
However doing something like that, globally, feels like bad practise.
second part of the question
This might sound like I cant decide what I want, but I want a way to modify all these switches/flags or whatever they are actually called in a single location, without tying any of my classes to it. I don't know if this is possible however.
Why don't I want to do that? Well I like to make my classes somewhat reusable and I don't like tying classes together, unless its required by the DRY principle and or inheritance. I basically couldn't get rid of the flags without modifying the possible hundreds of classes that used them.
What I have tried in the past
Having it all as compiler defines. This worked reasonably well, however I didnt like that I couldnt make it so if the flag file was gone there were some sort of default settings that would make the classes themselves still operational and changeable (through these default values)
Having it as a class and instancing it globally (system class). Worked ok, however I didnt like instancing anything globally. Also same problem as above
Instancing the system class locally and passing it to the classes on construction. This was kinda cool, since I could make multiple instruction sets. However at the same time that kinda ruined the point since it would lead to things that needed to have one flag set the same to have them set differently and therefore failing to properly work together. Also passing it on every construction was a pain.
A static class. This one worked ok for the longest time, however there is still the problem when there are missing dependencies.
Summary
Basically I am looking for a way to have a single "place" where I can mess with some values (bools, floats etc.) and that will change the behaviour of all classes using them for whatever, where said values either overwrite default values or get replaced by default values if said "place" isnt defined.
If a Singleton class does not work for you , maybe using a DI container may fit in your third approach? It may help with the construction and make the code more testable.
There are some DI frameworks for c++, like https://github.com/google/fruit/wiki or https://github.com/boost-experimental/di which you can use.
If you decide to use switch/flags, pay attention for "cyclometric complexity".
If you do not change the skeleton of your algorithm but only his behaviour according to the objets in parameter, have a look at "template design pattern". This method allow you to define a generic algorithm and specify particular step for a particular situation.
Here's an approach I found useful; I don't know if it's what you're looking for, but maybe it will give you some ideas.
First, I created a BehaviorFlags.h file that declares the following function:
// Returns true iff the given feature/behavior flag was specified for us to use
bool IsBehaviorFlagEnabled(const char * flagName);
The idea being that any code in any of your classes could call this function to find out if a particular behavior should be enabled or not. For example, you might put this code at the top of your ExtensionsAPI.cpp file:
#include "BehaviorFlags.h"
static const enableExtensionAPI = IsBehaviorFlagEnabled("enable_extensions_api");
[...]
void DoTheExtensionsAPIStuff()
{
if (enableExtensionsAPI == false) return;
[... otherwise do the extensions API stuff ...]
}
Note that the IsBehaviorFlagEnabled() call is only executed once at program startup, for best run-time efficiency; but you also have the option of calling IsBehaviorFlagEnabled() on every call to DoTheExtensionsAPIStuff(), if run-time efficiency is less important that being able to change your program's behavior without having to restart your program.
As far as how the IsBehaviorFlagEnabled() function itself is implemented, it looks something like this (simplified version for demonstration purposes):
bool IsBehaviorFlagEnabled(const char * fileName)
{
// Note: a real implementation would find the user's home directory
// using the proper API and not just rely on ~ to expand to the home-dir path
std::string filePath = "~/MyProgram_Settings/";
filePath += fileName;
FILE * fpIn = fopen(filePath.c_str(), "r"); // i.e. does the file exist?
bool ret = (fpIn != NULL);
fclose(fpIn);
return ret;
}
The idea being that if you want to change your program's behavior, you can do so by creating a file (or folder) in the ~/MyProgram_Settings directory with the appropriate name. E.g. if you want to enable your Extensions API, you could just do a
touch ~/MyProgram_Settings/enable_extensions_api
... and then re-start your program, and now IsBehaviorFlagEnabled("enable_extensions_api") returns true and so your Extensions API is enabled.
The benefits I see of doing it this way (as opposed to parsing a .ini file at startup or something like that) are:
There's no need to modify any "central header file" or "registry file" every time you add a new behavior-flag.
You don't have to put a ParseINIFile() function at the top of main() in order for your flags-functionality to work correctly.
You don't have to use a text editor or memorize a .ini syntax to change the program's behavior
In a pinch (e.g. no shell access) you can create/remove settings simply using the "New Folder" and "Delete" functionality of the desktop's window manager.
The settings are persistent across runs of the program (i.e. no need to specify the same command line arguments every time)
The settings are persistent across reboots of the computer
The flags can be easily modified by a script (via e.g. touch ~/MyProgram_Settings/blah or rm -f ~/MyProgram_Settings/blah) -- much easier than getting a shell script to correctly modify a .ini file
If you have code in multiple different .cpp files that needs to be controlled by the same flag-file, you can just call IsBehaviorFlagEnabled("that_file") from each of them; no need to have every call site refer to the same global boolean variable if you don't want them to.
Extra credit: If you're using a bug-tracker and therefore have bug/feature ticket numbers assigned to various issues, you can creep the elegance a little bit further by also adding a class like this one:
/** This class encapsulates a feature that can be selectively disabled/enabled by putting an
* "enable_behavior_xxxx" or "disable_behavior_xxxx" file into the ~/MyProgram_Settings folder.
*/
class ConditionalBehavior
{
public:
/** Constructor.
* #param bugNumber Bug-Tracker ID number associated with this bug/feature.
* #param defaultState If true, this beheavior will be enabled by default (i.e. if no corresponding
* file exists in ~/MyProgram_Settings). If false, it will be disabled by default.
* #param switchAtVersion If specified, this feature's default-enabled state will be inverted if
* GetMyProgramVersion() returns any version number greater than this.
*/
ConditionalBehavior(int bugNumber, bool defaultState, int switchAtVersion = -1)
{
if ((switchAtVersion >= 0)&&(GetMyProgramVersion() >= switchAtVersion)) _enabled = !_enabled;
std::string fn = defaultState ? "disable" : "enable";
fn += "_behavior_";
fn += to_string(bugNumber);
if ((IsBehaviorFlagEnabled(fn))
||(IsBehaviorFlagEnabled("enable_everything")))
{
_enabled = !_enabled;
printf("Note: %s Behavior #%i\n", _enabled?"Enabling":"Disabling", bugNumber);
}
}
/** Returns true iff this feature should be enabled. */
bool IsEnabled() const {return _enabled;}
private:
bool _enabled;
};
Then, in your ExtensionsAPI.cpp file, you might have something like this:
// Extensions API feature is tracker #4321; disabled by default for now
// but you can try it out via "touch ~/MyProgram_Settings/enable_feature_4321"
static const ConditionalBehavior _feature4321(4321, false);
// Also tracker #4222 is now enabled-by-default, but you can disable
// it manually via "touch ~/MyProgram_Settings/disable_feature_4222"
static const ConditionalBehavior _feature4222(4222, true);
[...]
void DoTheExtensionsAPIStuff()
{
if (_feature4321.IsEnabled() == false) return;
[... otherwise do the extensions API stuff ...]
}
... or if you know that you are planning to make your Extensions API enabled-by-default starting with version 4500 of your program, you can set it so that Extensions API will be enabled-by-default only if GetMyProgramVersion() returns 4500 or greater:
static ConditionalBehavior _feature4321(4321, false, 4500);
[...]
... also, if you wanted to get more elaborate, the API could be extended so that IsBehaviorFlagEnabled() can optionally return a string to the caller containing the contents of the file it found (if any), so that you could do shell commands like:
echo "opengl" > ~/MyProgram_Settings/graphics_renderer
... to tell your program to use OpenGL for its 3D graphics, or etc:
// In Renderer.cpp
std::string rendererType;
if (IsDebugFlagEnabled("graphics_renderer", &rendererType))
{
printf("The user wants me to use [%s] for rendering 3D graphics!\n", rendererType.c_str());
}
else printf("The user didn't specify what renderer to use.\n");
It is possible to automatically generate Sitecore templates just coding models? I'm using Sitecore 8.0 and I saw Glass Mapper Code First approach but I cant find more information about that.
Not sure why there isn't much info about it, but you can definitely model/code first!. I do it alot using the attribute configuration approach like so:
[SitecoreType(true, "{generated guid}")]
public class ExampleModel
{
[SitecoreField("{generated guid}", SitecoreFieldType.SingleLineText)]
public virtual string Title { get; set; }
}
Now how this works. The SitecoreType 'true' value for the first parameter indicates it may be used for codefirst. There is a GlassCodeFirstDataprovider which has an Initialize method, executed in Sitecore's Initialize pipeline. This method will collect all configurations marked for codefirst and create it in the sql dataprovider. The sections and fields are stored in memory. It also takes inheritance into account (base templates).
I think you first need to uncomment some code in the GlassMapperScCustom class you get when you install the project via Nuget. The PostLoad method contains the few lines that execute the Initialize method of each CodeFirstDataprovider.
var dbs = global::Sitecore.Configuration.Factory.GetDatabases();
foreach (var db in dbs)
{
var provider = db.GetDataProviders().FirstOrDefault(x => x is GlassDataProvider) as GlassDataProvider;
if (provider != null)
{
using (new SecurityDisabler())
{
provider.Initialise(db);
}
}
}
Furthermore I would advise to use code first on development only. You can create packages or serialize the templates as usual and deploy them to other environment so you dont need the dataprovider (and potential risks) there.
You can. But it's not going to be Glass related.
Code first is exactly what Sitecore.PathFinder is looking to achieve. There's not a lot of info publicly available on this yet however.
Get started here: https://github.com/JakobChristensen/Sitecore.Pathfinder
I have a solution with two different projects. I use SyntaxWalker to process some stuff in ProjectA.Class1. However, ProjectA.Class1 has reference ProjectB.Class2.
Is there way to allow the syntax walker to traverse also through external classes? I can't even do it when both classes are in the same project but in different files (documents). It always goes through the same document. If both classes are in the same file then it works. If I extract them to separate ones, it doesn't...
I am working on a test coverage tool. A user click on the method in VS and then:
I use rewriter to add static variables to each branch.
I run the code so the static variables are set if branch was covered.
I wonder how should I configure a syntax walker\rewriter to recognize other classes in the same solution.
You're going to need access to the Symbol API. A simple rule of thumb I try to go by:
The Syntax API is for individual files
The Symbol API allows you to work with information that spans across files.
You've mentioned in the comments that you'd like to traverse methods and figure out some information about each method declaration. Here's some (naive) code that should get you started with the symbol API.
I've assumed you've got access to a Project that you're analyzing.
Project myProject;
public void ProcessMethod(MethodDeclarationSyntax method)
{
//Get the semantic model
var filePath = method.SyntaxTree.FilePath;
var containingDocument = myProject.Documents.Where(n => n.FilePath == filePath).Single();
var model = containingDocument.GetSemanticModelAsync().Result;
//...
//Do your processing on the current method here...
//...
//Process the invoked methods.
var invocations = method.DescendantNodes().OfType<InvocationExpressionSyntax>();
foreach(var invocation in invocations)
{
var invokedSymbol = model.GetSymbolInfo(invocation).Symbol; //Might be null
var invokedSymbolSyntax = (MethodDeclarationSyntax)invokedSymbol.DeclaringSyntaxReferences.First().GetSyntax(); //Partial methods might be declared in multiple places
ProcessMethod(invokedSymbolSyntax);
}
}
Note:
This approach doesn't handle constructors, destructors, properties, expression-bodied members and any other members I've forgotten. But it should be enough to get you started and introduce you to the symbol API.
Recursion will bite you.
You won't process implementations of interfaces. You'll have to look into the SymbolFinder for that.
Is it possible to use JavaLoader to get objects returned by CF-called web services, and JavaLoader-loaded objects to be the same classpath context? I mean, without a lot of difficulty?
// get a web service
ws = createObject("webservice", local.lms.wsurl);
// user created by coldfusion
user = ws.GenerateUserObject();
/* user status created by java loader.
** this api provider requires that you move the stubs
** (generated when hitting the wsdl from CF for the first time)
** to the classpath.
** this is one of the stubs/classes that gets called from that.
*/
UserStatus = javaLoader.create("com.geolearning.geonext.webservices.Status");
// set user status: classpath context clash
user.setStatus(UserStatus.Active);
Error:
Detail: Either there are no methods with the specified method name and
argument types or the setStatus method is overloaded with argument
types that ColdFusion cannot decipher reliably. ColdFusion found 0
methods that match the provided arguments. If this is a Java object
and you verified that the method exists, use the javacast function to
reduce ambiguity.
Message: The setStatus method was not found.
MethodName setStatus
Even though the call, on the surface, matches a method signature on user--setStatus(com.geolearning.geonext.webservices.Status)--the class is on a different classpath context. That's why I get the error above.
Jamie and I worked on this off-line and came up with a creative solution :)
(Apologies for the long answer, but I thought a bit of an explanation was warranted for those who find class loaders as confusing as I do. If you are not interested in the "why" aspect, feel free to jump to the end).
Issue:
The problem is definitely due to multiple class loaders/paths. Apparently CF web services use a dynamic URLClassLoader (just like the JavaLoader). That is how it can load the generated web service classes on-the-fly, even though those classes are not in the core CF "class path".
(Based on my limited understanding...) Class loaders follow a hierarchy. When multiple class loaders are involved, they must observe certain rules or they will not play well together. One of the rules is that child class loaders can only "see" objects loaded by an ancestor (parent, grandparent, etcetera). They cannot see classes loaded by a sibling.
If you examine the object created by the JavaLoader, and the other by createObject, they are indeed siblings ie both children of the CF bootstrap class loader. So the one will not recognize objects loaded by the other, which would explain why the setStatus call failed.
Given that a child can see objects loaded by a parent, the obvious solution is to change how the objects are constructed. Structure the calls so that one of the class loaders ends up as a parent of the other. Curiously that turned out to be trickier than it sounded. I could not find a way to make that happen, despite trying a number of combinations (including using the switchThreadContextClassLoader method).
Solution:
Finally I had a crazy thought: do not load any jars. Just use the web service's loader as the parentClassLoader. It already has everything it needs in its own individual "class path":
// display class path of web service class loader
dynamicLoader = webService.getClass().getClassLoader();
dynamicClassPath = dynamicLoader.getURLS();
WriteDump("CLASS PATH: "& dynamicClassPath[1].toString() );
The JavaLoader will automatically delegate calls for classes it cannot find to parentClassLoader - and bingo - everything works. No more more class loader conflict.
webService = createObject("webservice", webserviceURL, webserviceArgs);
javaLoader = createObject("component", "javaloader.JavaLoader").init(
loadPaths = [] // nothing
, parentClassLoader=webService.getClass().getClassLoader()
);
user = webService.GenerateUserObject();
userStatus = javaLoader.create("com.geolearning.geonext.webservices.Status");
user.setStatus(userStatus.Active);
WriteDump(var=user.getStatus(), label="SUCCESS: user.getStatus()");