I am using the PostContextCreate part of the life cycle in an e4 RCP application to create the back-end "business logic" part of my application. I then inject it into the context using an IEclipseContext. I now have a requirement to persist some business logic configuration options between executions of my application. I have some questions:
It looks like properties (e.g. accessible from MContext) would be really useful here, a straightforward Map<String,String> sounds ideal for my simple requirements, but how can I get them in PostContextCreate?
Will my properties persist if my application is being run with clearPersistedState set to true? (I'm guessing not).
If I turn clearPersistedState off then will it try and persist the other stuff that I injected into the context?
Or am I going about this all wrong? Any suggestions would be welcome. I may just give up and read/write my own properties file.
I think the Map returned by MApplicationElement.getPersistedState() is intended to be used for persistent data. This will be cleared by -clearPersistedState.
The PostContextCreate method of the life cycle is run quite early in the startup and not everything is available at this point. So you might have to wait for the app startup complete event (UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) before accessing the persisted state data.
You can always use the traditional Platform.getStateLocation(bundle) to get a location in the workspace .metadata to store arbitrary data. This is not touched by clearPersistedState.
Update:
To subscribe to the app startup complete:
#PostContextCreate
public void postContextCreate(IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new AppStartupCompleteEventHandler());
}
private static final class AppStartupCompleteEventHandler implements EventHandler
{
#Override
public void handleEvent(final Event event)
{
... your code here
}
}
Related
I'm building my first event sourced system. It will have multiple domains using projects with a publication lifecycle at it's core. How can I effectively replay or re-apply events of two domains to a new aggregate inside a third domain?
To be more specific. Imagine 4 domains each with their own bounded context and purpose. A short description of these contexts:
Project - A project is a complex object at the core of the system, almost every domain requires project data to operate. A project has one or more ProductTypes which contain the limited supply of Products.
Media - The media domain covers operations around images, documents and generated reports and functions as a file server.
Delivery - Delivery allows for the configuration of which content channels to publish all publications to.
Publication - The publication domain handles the complex tasks of verifying if a project can be published to the requested status in it's current state.
The states of publication follow the lifecycle: concept (not yet published) > announced (optional) > sale > sold-out (publication ended). In my description I focus on the announced status. Concept is not actually a thin for the publication domain since a project is always in concept if publication does not know about it yet.
My first attempt was setting up a normal aggregate which handled the incoming event AnnouncementPublishedEvent. This requires a project to meet some basic requirements like 'it has a name', 'it has a description', 'it has at least one image' and so on. This means I need to validate this information before the event is applied and therefore I somehow need to supply a project instance in the command.
While doing this I suspected this method breaks the purpose of CQRS and I should be looking at the real data source: events. My next attempt was creating a Saga that starts when the event AnnouncementPublicationRequestedEvent. This saga needs to review which events occured around the given projectId and apply those to this new 'published project' projection in order to (at least) validate if the request can be accepted.
I researched and experimented with tracking processors but could not get a good example how this is done in version 4 of Axon. I also started to read several other questions on Stackoverflow that made me think I might need to reconsider my approach.
Unfortunately, the exact code can not be shared as it's not open source and even if I could it's far from a working state. I can use example code to show what I'm trying to do.
#Saga
#ProcessingGroup("AnnouncementPublication")
public class AnnouncementPublicationSaga {
private static int NUMBER_OF_ALLOWED_IMAGES
private PublicationId publicationId;
private ProjectId projectId;
private int numberOfImages = 0;
//...other fields
#StartSaga
#SagaEventHandler(associationProperty = "projectId")
public void handle(AnnouncementPublicationRequestedEvent event) {
publicationId = generatePublicationId();
//set parameters from event for saga to use
projectId = event.getProjectId();
targetPublicationStatus = event.getPublicationStatus();
date = event.getDate();
//initialize the 'publicated project' aggregate
//start a replay of associated events for this #ProcessingGroup
}
...
#SagaEventHandler(associationProperty = "projectId")
public void handle(ProjectCreatedEvent event) {
//Verify the project exists and has a valid name
}
...
/* Assumption* on how AssociationResolver works: */
#SagaEventHandler(AssociationResolver=MediaProjectAssociator.class )
public void handle(ProjectImageAdded event) {
numberOfImages += 1;
}
/* Assumption* on how AssociationResolver works: */
#SagaEventHandler(AssociationResolver=MediaProjectAssociator.class )
public void handle(ProjectImageRemoved event) {
numberOfImages -= 1;
}
...
/* In my head this should trigger if all events have been played
up to the PublicationRequestedEvent. Or maybe
*/
#SagaEventHandler(associationProperty = "publicationId")
public void handle(ValidationRequestCompleted event) {
//ValidationResult result = ValidationResult.builder();
...
if (numberOfImages > NUMBER_OF_ALLOWED_IMAGES) {
//reason to trigger PublicationRequestDeniedEvent
//update validationResult
}
...
if (validationResult.isAcceptable()) {
//Trigger AnnouncementPublicationAcceptedEvent
} else {
//Trigger AnnouncementPublicationDeniedEvent
}
}
...
#EndSaga
#SagaEventHandler(associationProperty = "publicationId")
public void handle(AnnouncementPublicationDeniedEvent event) {
//do stuff to inform why the publication failed
}
#EndSaga
#SagaEventHandler(associationProperty = "publicationId")
public void handle(AnnouncementPublicationAcceptedEvent event){
//do stuff to notify success to user
//choice: delegate to delivery for actual sharing of data
// or delivery itselfs listens for these events
}
}
*The associationResolver code is an assumption to it's actual working as I'm not even close to that part yet. My media context uses a file id as aggregate identifier as not every event is bound to a project. But all the media events this saga needs to replay will have a projectId as field in them. Any feedback on this is welcome but it's not my main problem now.
In the end the result should be: a record of the publication or a record of the attempt and why it failed.
The record of the publication contains all data from project or media events that are relevant to a publication. This is mostly information that potential buyers need to make a decision.
For the purpose of this question I don't expect the above to be solved completely. I just want to know if I'm on the right track with thinking in events, if my approach on replaying relevant events is the right way to go and if so how this can be done in Axon4.
From your problem description Martin, I assume you have several distinct Bounded Contexts. Following the definition of Bounded Context:
Explicitly define the context within which a model applies.
Explicitly set boundaries in terms of team organization,
usage within specific parts of the application,
and physical manifestations such as code bases and database schemas.
Keep the model strictly consistent within these bounds,
but don’t be distracted or confused by issues outside.
From this I'd like to emphasize that within a given Bounded Context, you speak the same language/API with any component.
Between contexts, you will however share very consciously, using dedicated context-mappings like for example an anti-corruption layer to ensure another domain doesn't enter your domain.
Having said the above, events are part of a specific Bounded Context.
Thus, using multiple streams of events from other contexts to recreate/replay an aggregate in another context should ideally be out of the question.
On top of this, in Axon an Aggregate can only ever be recreated based on events it has published itself.
To still arrive to a solution where a given application ingests events from other applications to re-hydrate an Aggregate, I would take the following steps:
Have a dedicated component (e.g. the anti-corruption layer) which translates the incoming events into a different form of message within your application.
If these events should result in the reconstruction of an Aggregate, you are required to make translate the events to commands. The Aggregate infrastructure components in Axon are meant for the Command Model when talking about CQRS.
Said Aggregate would then handle the commands, perform some business logic and publish an event (or several) as a result.
From here on out, the Framework will deal with replaying all events for the given Aggregate, granted you follow Event Sourcing practices to update the Aggregate's state.
Lastly, I'd like to point out that any specifics provided by Axon around replaying tied to the TrackingEventProcessor are meant for Event Processing on the Query side of a CQRS application.
Hope this clarifies things for you Martin! If not, feel free to comment under this answer and I'll update my response accordingly.
I have essentially the same question as here but am hoping to get a less vague, more informative answer.
I'm looking for a way to configure DropWizard programmatically, or at the very least, to be able to tweak configs at runtime. Specifically I have a use case where I'd like to configure metrics in the YAML file to be published with a frequency of, say, 2 minutes. This would be the "normal" default. However, under certain circumstances, I may want to speed that up to, say, every 10 seconds, and then throttle it back to the normal/default.
How can I do this, and not just for the metrics.frequency property, but for any config that might be present inside the YAML config file?
Dropwizard reads the YAML config file and configures all the components only once on startup. Neither the YAML file nor the Configuration object is used ever again. That means there is no direct way to configure on run-time.
It also doesn't provide special interfaces/delegates where you can manipulate the components. However, you can access the objects of the components (usually; if not you can always send a pull request) and configure them manually as you see fit. You may need to read the source code a bit but it's usually easy to navigate.
In the case of metrics.frequency you can see that MetricsFactory class creates ScheduledReporterManager objects per metric type using the frequency setting and doesn't look like you can change them on runtime. But you can probably work around it somehow or even better, modify the code and send a Pull Request to dropwizard community.
Although this feature isn't supported out of the box by dropwizard, you're able to accomplish this fairly easy with the tools they give you. Note that the below solution definitely works on config values you've provided, but it may not work for built in configuration values.
Also note that this doesn't persist the updated config values to the config.yml. However, this would be easy enough to implement yourself simply by writing to the config file from the application. If anyone would like to write this implementation feel free to open a PR on the example project I've linked below.
Code
Start off with a minimal config:
config.yml
myConfigValue: "hello"
And it's corresponding configuration file:
ExampleConfiguration.java
public class ExampleConfiguration extends Configuration {
private String myConfigValue;
public String getMyConfigValue() {
return myConfigValue;
}
public void setMyConfigValue(String value) {
myConfigValue = value;
}
}
Then create a task which updates the config:
UpdateConfigTask.java
public class UpdateConfigTask extends Task {
ExampleConfiguration config;
public UpdateConfigTask(ExampleConfiguration config) {
super("updateconfig");
this.config = config;
}
#Override
public void execute(Map<String, List<String>> parameters, PrintWriter output) {
config.setMyConfigValue("goodbye");
}
}
Also for demonstration purposes, create a resource which allows you to get the config value:
ConfigResource.java
#Path("/config")
public class ConfigResource {
private final ExampleConfiguration config;
public ConfigResource(ExampleConfiguration config) {
this.config = config;
}
#GET
public Response handleGet() {
return Response.ok().entity(config.getMyConfigValue()).build();
}
}
Finally wire everything up in your application:
ExampleApplication.java (exerpt)
environment.jersey().register(new ConfigResource(configuration));
environment.admin().addTask(new UpdateConfigTask(configuration));
Usage
Start up the application then run:
$ curl 'http://localhost:8080/config'
hello
$ curl -X POST 'http://localhost:8081/tasks/updateconfig'
$ curl 'http://localhost:8080/config'
goodbye
How it works
This works simply by passing the same reference to the constructor of ConfigResource.java and UpdateConfigTask.java. If you aren't familiar with the concept see here:
Is Java "pass-by-reference" or "pass-by-value"?
The linked classes above are to a project I've created which demonstrates this as a complete solution. Here's a link to the project:
scottg489/dropwizard-runtime-config-example
Footnote: I haven't verified this works with the built in configuration. However, the dropwizard Configuration class which you need to extend for your own configuration does have various "setters" for internal configuration, but it may not be safe to update those outside of run().
Disclaimer: The project I've linked here was created by me.
I solved this with bytecode manipulation via Javassist
In my case, I wanted to change the "influx" reporter
and modifyInfluxDbReporterFactory should be ran BEFORE dropwizard starts
private static void modifyInfluxDbReporterFactory() throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("com.izettle.metrics.dw.InfluxDbReporterFactory"); // do NOT use InfluxDbReporterFactory.class.getName() as this will force the class into the classloader
CtMethod m = cc.getDeclaredMethod("setTags");
m.insertAfter(
"if (tags.get(\"cloud\") != null) tags.put(\"cloud_host\", tags.get(\"cloud\") + \"_\" + host);tags.put(\"app\", \"sam\");");
cc.toClass();
}
I have looked around and around for this answer, but I have not been able to find a good answer. I would like to create a system based on Quartz that allows people to schedule their own tasks. I will use a pseudo example.
Let's say my main method for my Quartz program is called quartz.java.
Then I have a file called sweep.java that implements the Quartz "job" interface.
So in my quartz.java, I schedule my sweep.java to run every hour. I run quartz.java, and it works fine. GREAT; however, now I want to add a dust.java to the quartz scheduler; however, since this is a production service, I don't want to have to stop my quartz.java file, add in my dust.java, and recompile and run quartz.java again. This downtime would be unacceptable.
Does anyone have any ideas on how I could accomplish this? It seems impossible because how could you ever feed another java file into the program without recompiling, linking, etc.
I hope that this example is clear. Please let me know if I need to clarify any part of it.
Partial answer: it is possible to compile, and then instantiate, a class, programatically.
Here are links to example code:
how to compile from a String;
CompilerOutput;
CompilerOutputDirectory.
The extracted class is grabbed in the third source file (see method getGeneratedClass, which returns a Class<?> object).
HOWEVER: keep in mind that this is potentially dangerous to do so. One problem, which can be quite serious if you are not careful, is that when you dynamically instantiate a class, its static initialization blocks are executed. And these can potentially wreak havoc on your application. So, in addition, you'll have to create an appropriate SecurityContext.
In the code above, I actually only ever get the Class<?> object and never instantiate it in any way, so no code is executed. But your usage scenario is quite different.
I have not tried any of these but are worth trying .
1) Consider using Quartz camel endpoint .
If my understanding is right, Apache Camel lets you create the camel routes on the fly.
It just needs to deploy the camel-context.xml into a container taking into consideration that the required classes would be already available on classpath of container.
2) Quartz lets you create a job declaratively i.e. with xml configuration of job and trigger.
You can find more information here.
3) Now this requires some efforts ;-)
Create an interface which has a method which you will execute as a part of job. Lets say this will have a method called
public interface MyDynamicJob
{
public void executeThisAsPartOfJob();
}
Create your instances of Job methods.
public EmailJob implements MyDynamicJob
{
#Override
public void executeThisAsPartOfJob()
{
System.out.println("Sending Email");
}
}
Now in your main scheduler engine, use the Observer pattern to store/initiate the job dynamically.
Something like,
HashMap jobs=new HashMap<String,MyDynamicJob>();
// call this method to add the job dynamically.
// If you add a job after the scheduler engine started , find a way here how to reiterate over this map without shutting down the scheduler :-).
public void addJob(String someJobName,MyDynamicJob job)
{
jobs.add(someJobName,job);
}
public void initiateScheduler()
{
// Iterate over the jobs map to get all registered jobs. Create
// Create JobDetail instances dynamically for each job Entry. add your custom job class as a part of job data map.
Job jd1=JobBuilder.newJob(GenericJob.class)
.withIdentity("FirstJob", "First Group").build();
Map jobDataMap=jd1.getJobDataMap();
jobDataMap.put("dynamicjob", jobs.get("dynamicjob1"));
}
public class GenericJob implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("Executing job");
Map jdm=arg0.getJobDetail().getJobDataMap();
MyDynamicJob mdj=jdm.get("dynamicjob");
// Now execute your custom job method here.
mdj.executeThisAsPartOfJob();
System.out.println("Job Execution complete");
}
}
My application loads entities from a Hibernate DAO, with OpenSessionInViewFilter to allow rendering.
In some cases I want to make a minor change to a field -
Long orderId ...
link = new Link("cancel") {
#Override public void onClick() {
Order order = orderDAO.load(orderId);
order.setCancelledTime(timeSource.getCurrentTime());
};
but such a change is not persisted, as the OSIV doesn't flush.
It seems a real shame to have to call orderDOA.save(order) in these cases, but I don't want to go as far as changing the FlushMode on the OSIV.
Has anyone found any way of declaring a 'request handling' (such as onClick) as requiring a transaction?
Ideally I suppose the transaction would be started early in the request cycle, and committed by the OSIV, so that all logic and rendering would take place in same transaction.
I generally prefer to use additional 'service' layer of code that wraps basic DAO
logic and provides transactions via #Transactional. That gives me better separation of presentation vs business logic and is
easier to test.
But since you already use OSIV may be you can just put some AOP interceptor around your code
and have it do flush()?
Disclaimer : I've never actually tried this, but I think it would work. This also may be a little bit more code than you want to write. Finally, I'm assuming that your WebApplication subclasses SpringWebApplication. Are you with me so far?
The plan is to tell Spring that we want to run the statements of you onClick method in a transaction. In order to do that, we have to do three things.
Step 1 : inject the PlatformTransactionManager into your WebPage:
#SpringBean
private PlatformTransactionManager platformTransactionManager;
Step 2 : create a static TransactionDefinition in your WebPage that we will later reference:
protected static final TransactionDefinition TRANSACTION_DEFINITION;
static {
TRANSACTION_DEFINITION = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
((DefaultTransactionDefinition) TRANSACTION_DEFINITION).setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
}
Feel free to change the TransactionDefinition settings and/or move the definition to a shared location as appropriate. This particular definition instructs Spring to start a new transaction even if there's already one started and to use the maximum transaction isolation level.
Step 3 : add transaction management to the onClick method:
link = new Link("cancel") {
#Override
public void onClick() {
new TransactionTemplate(platformTransactionManager, TRANSACTION_DEFINITION).execute(new TransactionCallback() {
#Override
public Object doInTransaction(TransactionStatus status) {
Order order = orderDAO.load(orderId);
order.setCancelledTime(timeSource.getCurrentTime());
}
}
}
};
And that should do the trick!
My spaghetti monster consumes XML from several different SOAP services, and the URL for each service is hardcoded into the application. I'm in the process of undoing this hardcoding, and storing the URLs in a properties file.
In terms of reading the properties file, I'd like to encompass that logic in a Singleton that can be referenced as needed.
Change this:
accountLookupURL ="http://prodServer:8080/accountLookupService";
To this:
accountLookupURL =urlLister.getURL("accountLookup");
The Singleton would be contained within the urlLister.
I've tended to shy away from the Singleton pattern, only because I've not had to use it, previously. Am I on the right track, here?
Thanks!
IVR Avenger
You haven't said why you need only one of whatever it is which will be getting the URL. If that just involves reading a properties file, I don't think you do need only one. Seems to me that having two threads read the same properties file at the same time isn't a problem at all.
Unless you were thinking of having some object which only reads the properties file once and then caches the contents for future use. But this is a web application, right? So the way to deal with that is to read in the properties when the application starts up, and store them in the application context. There's only one application context, so there's your "only one" object.
As an alternative, did you consider using something like Apache Commons Configuration (or maybe another configuration framework)?
Singletons are appropriate for this scenario, BUT you have to make sure you're doing the singleton right.
So, for example, what Bozhno suggests is not a singleton, it's an ugly concoction of nasty statics that's not mockable, not easily testable, not injectable, and generally comes back to bite you in the ass.
An acceptable singleton is just your average class with one notable exception that it is guaranteed either by itself or by some external factory/framework (e.g Spring IoC) to exist in only one instance. If you go with the first approach, you do something like
private MyUberSingletonClass() {
//..do your constructor stuff, note it's private
}
private static MyUberSingletonClass instance = null;
public static synchronized MyUberSingletonClass instance() {
if (instance == null) {
instance = new MyUberSingletonClass();
}
return instance;
}
public String getUberUsefulStuff(){
return "42";
}
That's acceptable if you don't really feel the need for a factory otherwise, and aren't using any IoC container in your app (good idea to think about using one though). Note the difference from Bozhno's example: this is a good vanilla class where the only static is an instance var and a method to return it. Also note the synchronized keyword required for lazy-initialization.
update: Pascal recommends this very cool post about a better way to lazy-init singletons in the comments below: http://crazybob.org/2007/01/lazy-loading-singletons.html
Based on your suggestions, and the fact that I don't think I have as much access to this application as I'd hoped (a lot of it is abstracted away in compiled code), here's the solution I've cooked up. This is, of course, a stub, and needs to be fleshed out with better exception handling and the like.
public class WebServiceURLs {
private static class WebServiceURLsHolder
{
public static WebServiceURLs webServiceURLs = new WebServiceURLs();
}
private Properties webServiceURLs;
public WebServiceURLs()
{
try
{
Properties newURLProperties = new Properties();
InputStreamReader inputStream = new InputStreamReader(
FileLoader.class.getClassLoader().getResourceAsStream("../../config/URLs.properties") );
newURLProperties.load(inputStream);
webServiceURLs =newURLProperties;
}
catch (Exception e)
{
webServiceURLs =null;
}
}
public String getURLFromKey(String urlKey)
{
if (webServiceURLs==null)
return null;
else
return webServiceURLs.getProperty(urlKey);
}
public static WebServiceURLs getInstance()
{
return WebServiceURLsHolder.webServiceURLs;
}
}
Is this a good effort as my "first" Singleton?
Thanks,
IVR Avenger
To restate the obvious, Singleton is to be used when all client code should talk to a single instance of the class. So, use a Singleton IFF you are certain that you would not want to load multiple properties files at once. Personally, I would want to be able to have that functionality (loading multiple properties files).
Singletons are mutable statics and therefore evil. (Assuming a reasonably useful definition of "singleton".
Any code that uses the static (a transitive relationship), is has assumptions about pretty much everything else (in this case, a web server and the internet). Mutable statics are bad design, and bad design makes many aspects go rotten (dependency, understandability, testing, security, etc).
As an example, the only thing stopping late versions of JUnit 3 being used in a sandbox was loading a configuration file in one static initialiser. If it had used Parameterisation from Above, there would have been no issue.