-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Enhanced extension support #1512
Comments
Some further goals for improving the extension system I think we should prioritise:
|
For discussion, some options:
Which do we prefer? |
For example, taking In 1) we'd change ResponseDefinition transform(ServeEvent serveEvent); In 2) we'd deprecate ResponseDefinition transform(ServeEvent serveEvent); In 3) we'd support something like this so that : @Inject
public ResponseDefinitionTransformer(CurrentServeEvent currentServeEvent,
SubEvents subEvents,
FileSource fileSource) {
this.currentServeEvent = currentServeEvent;
this.subEvents = subEvents;
this.fileSource = fileSource;
} |
Just a couple of questions here, from someone who is not very familiar with the internal code structure: For 1), I see the appeal of being able to implement multiple extension interfaces in a single class, but it might also lead to people creating For 3), that last method signature suggestion confuses me. Is there no inherent relation (through inheritance or composition) between a |
My experience of not being able to implement multiple interfaces is that you have to write quite messy code to share behaviour/state between parts that use different extension hooks. My personal view is that the tradeoff is worth it.
Arguably a) could be fixed by creating an empty I've probably biased myself in that created a branch with an attempt at doing this, and it's broken a load of stuff in obscure ways, so to some extent I'm probably just trying to avoid the work :-) |
One more potential addition that I think would be useful:
|
Thanks, @tomakehurst, that makes sense. |
I've pushed a set of changes in line with the above suggestions to a branch: It's ended up pretty huge, which was necessary to keep all the tests green, but I'm pretty happy with it as a design. Key bits worth looking at: |
is it possible to adjust the names e.g. for |
Trying to integrate this into https://github.com/dirkbolte/wiremock-extension-state , I wondered how we can integrate an Event Listener with different parameters for different events. If my extension has functionalities for multiple events, I would define it like this: .withServeEventListener(
"MyListener",
Parameters.from(Map.of("afterMatchKey", "afterMatchValue"))
)
.withServeEventListener(
"MyListener",
Parameters.from(Map.of("afterCompleteKey", "afterCompleteValue"))
) The Listener wouldn't know which parameters are meant for which context. So either I have to add my own parameter saying "only for event a,b,c") or we can somehow define this from outside. |
Would it not be practical in this case to create different listener implementation classes so you'd have e.g. one called |
Definitely. But it would require to register all extensions explicitly which might be error prone and not that nice to handle. I think I would be ideal if we have only one extension registration for instantiating all parts of a extension. If it's not practical to implement all interface methods or actually encouraged to split implementations up, it feels like the interfaces should be segregated - or bind the definition to an event. |
OK, so perhaps an interface like this would work: public interface ServeEventListener extends Extension {
enum EventType {
BEFORE_MATCH,
AFTER_MATCH,
AFTER_COMPLETE
}
default void onEvent(EventType eventType, ServeEvent serveEvent, Parameters parameters) {}
default boolean applyGlobally() {
return true;
}
default List<EventType> getEventTypes() {
return List.of(EventType.values());
}
} And then we'd also allow event types to be specified per-stub e.g.: .withServeEventListener(
EventType.AFTER_MATCH,
"MyListener",
Parameters.from(Map.of("afterMatchKey", "afterMatchValue"))
)
.withServeEventListener(
EventType.AFTER_COMPLETE,
"MyListener",
Parameters.from(Map.of("afterCompleteKey", "afterCompleteValue"))
) |
That would definitely address my concern. |
Or better still, so you could work either way: public interface ServeEventListener extends Extension {
enum RequestPhase {
BEFORE_MATCH,
AFTER_MATCH,
AFTER_COMPLETE
}
default void onEvent(RequestPhase requestPhase, ServeEvent serveEvent, Parameters parameters) {
switch (requestPhase) {
case BEFORE_MATCH:
beforeMatch(serveEvent, parameters);
break;
case AFTER_MATCH:
afterMatch(serveEvent, parameters);
break;
case AFTER_COMPLETE:
afterComplete(serveEvent, parameters);
break;
}
}
default void beforeMatch(ServeEvent serveEvent, Parameters parameters) {}
default void afterMatch(ServeEvent serveEvent, Parameters parameters) {}
default void afterComplete(ServeEvent serveEvent, Parameters parameters) {}
default boolean applyGlobally() {
return true;
}
default List<RequestPhase> getEventTypes() {
return List.of(RequestPhase.values());
}
} |
…ment) to allow generic listeners to be written then bound to specific request phases + parameters
@dirkbolte please take a look at 9670363 - hopefully this will do what you're looking for. |
@tomakehurst Should we consider this issue as done? |
WireMock extensions could be made easier to implement and easier to install. The intention of this issue is to collect areas of improvement and ideas for improving them.
My initial thoughts on what could be improved:
FileSource
but sometimes not. Providing abstractions for all the obvious use cases would allow extensions to be more portable between environments e.g. default providers could be file-backed, but with e.g. S3 as an alternative for when you're running in a container in AWS with no writable file system available.Some ideas for improvement:
Comments welcome on other ways this could be improved.
The text was updated successfully, but these errors were encountered: