I would like to get the Story name in a method annotated with #BeforeStory.
I need this for debugging purposes, cause i'm running a bunch of stories with runStoriesAsPaths and with multiple threads, and I'm trying to log which thread is running which story.
Is there a way to do this?
first you need to create a new StoryReporter (extend that class). In that class you can add actions to be performed before/after story/scenario/step, and you have the story name.
example:
public class NewStoryReporter implements StoryReporter {
private StoryReporter delegate;
public NewStoryReporter(StoryReporter delegate) {
this.delegate = delegate;
}
#Override
public void beforeStory(Story story, boolean givenStory) {
delegate.beforeStory(story, givenStory);
}
#Override
public void beforeScenario(String scenarioTitle) {
delegate.beforeScenario(scenarioTitle);
}
#Override
public void beforeStep(String step) {
if(step.equals("When after each step")){
return;
}
delegate.beforeStep(step);
}
then you need to extend StoryReporterBuilder, this creates your NewStoryReporter.
example:
public class NewStoryReporterBuilder extends StoryReporterBuilder {
#Override
public StoryReporter build(String storyPath) {
StoryReporter delegate = super.build(storyPath);
return new NewStoryReporter(delegate);
}
}
then in your configuration, create an instance of the NewStoryReporterBuilder, and use it in
Configuration configuration = new YourConfiguration().useStoryReporterBuilder(newStoryReporterBuilder....)
Now in Jbehave it's configured in different way.
So, to achieve that goal you need to:
Create new class which extends org.jbehave.core.reporters.ConsoleOutput. Here you can modify various of methods. In your case - you need to override method:
public void beforeScenario(String title)
Check example attached in the end of this post to see how it can be done.
Create new instance of abstract class org.jbehave.core.reporters.Filter:
public static final Format YOUR_CUSTOM_CONSOLE = new Format("YOUR_CUSTOM_CONSOLE")
{
#Override
public StoryReporter createStoryReporter(FilePrintStreamFactory factory,
StoryReporterBuilder storyReporterBuilder) {
return new TeamCityConsoleOutput(storyReporterBuilder.keywords()).doReportFailureTrace(
storyReporterBuilder.reportFailureTrace()).doCompressFailureTrace(
storyReporterBuilder.compressFailureTrace());
}
};
Then you need to add this format to your story builder which you are using in your configuration, that mean:
new MostUsefulConfiguration()
.useStoryReporterBuilder(
new StoryReporterBuilder()
....//here are another modifications of sorey report builder
.withFormats(YOUR_CUSTOM_CONSOLE , .../* another formats */ HTML, Format.XML, Format.TXT))
....//here are another modifications of configuration
.useStepMonitor(new CrossReference().getStepMonitor());
Here is example of such modification, which can be used to integration with TeamCity:
https://github.com/jbehave/jbehave-core/blob/d15774bf763875662869cdc89ce924b1086af6f8/jbehave-core/src/main/java/org/jbehave/core/reporters/TeamCityConsoleOutput.java
Related
I'm looking for a way to remove stacktraces of fails assertions when using the framework Citrus.
This is done in testNg like this:
public class NoStackTraceListener implements ITestListener {
...
#Override
public void onTestFailure(ITestResult iTestResult) {
Throwable th = iTestResult.getThrowable();
if (Objects.nonNull(th)) {
System.out.println(th.getMessage());
iTestResult.setThrowable(null);
}
}
...
}
#Listeners({ NoStackTraceListener.class })
class A {...}
But I can't find any example of usgin the class 'TestListener' or others in order to override the supplied implementation of 'LoggingReporter'
Please do anyone has already overrided a Listener using framework citrus and could give the snippet to do so ?
Thanks
You need to add the custom reporter as bean to the Spring application context:
#Bean
public NoStackTraceReporter noStackTraceReporter() {
return new NoStackTraceReporter();
}
You can also overwrite the default logging reporter by choosing the bean name loggingReporter
#Bean
public NoStackTraceReporter loggingReporter() {
return new NoStackTraceReporter();
}
The NoStackTraceReporter implementation is then able to overwrite the specific event handler for failed tests:
public class NoStackTraceReporter extends LoggingReporter {
...
#Override
public void onTestFailure(TestCase test, Throwable cause) {
// do something customized
}
...
}
Also you may overwrite the generateTestResults() method in the reporter interface in order to customize logging results.
You can also follow the sample http://www.citrusframework.org/samples/reporting/ that demonstrates how to add customized reporters in Citrus.
I'm new to Jersey 2 and JAX-RS, so probably I'm missing something.
What I'm trying to do is a test program to define a coding style in rest services developing.
The test was written in JAVA and uses JERSEY 2.22.2, JDK 1.8.31, MOXY AS JSON Provider.
I defined a Resource with GET methods to support LIST/DETAIL. Due to the size of my POJO, I used some filters and everything was fine.
// 1) First of all I defined the annotation.
#Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#EntityFiltering
public #interface MyDetailView {
public static class Factory extends AnnotationLiteral<MyDetailView>
implements MyDetailView {
private Factory() {
}
public static MyDetailView get() {
return new Factory();
}
}
// 2) Once defined the annotation, I used to
// programmaticaly exclude the list of subItems in the response...
#XmlRootElement
public class MyPojo {
...
//*** THIS SHOULD BE FILTERED IF THE ANNOTATION IS NOT SPECIFIED IN THE RESPONSE ***
#MyDetailView
private List<SubItem> subItems = new ArrayList<SubItem>();
public List<SubItem> getSubItems() {
return subItems;
}
public void setSubItems(List<SubItem> subItems) {
this.subItems = subItems;
}
}
// 3) I registered the EntityFilteringFeature
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
....
register(EntityFilteringFeature.class);
}
// 4) Finally, I wrote the code to include/exclude the subItems
/*
The Resource class has getCollection() and getItem() methods...
getCollection() adds the annotation only if filterStyle="detail"
getItem() always add the annotation
*/
#Path(....)
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class MyResource extends SecuredResource {
//filterStyle -> "detail" means MyDetailAnnotation
#GET
public Response getCollection(
#QueryParam("filterStyle") String filterStyle,
#Context UriInfo uriInfo) {
//THIS CODE AFFECTS THE RESPONSE
boolean detailedResponse = "detail".equals(filterStyle);
Annotation[] responseAnnotations = detailedResponse
? new Annotation[0]
: new Annotation[]{MyDetailView.Factory.get()};
//pojo collection...
MyPagedCollection myCollection = new MyPagedCollection();
//.....
ResponseBuilder builder = Response.ok();
return builder.entity(myCollection, responseAnnotations).build();
}
#GET
#Path("/{id}")
public Response getItem(#PathParam("{id}") String idS, #Context UriInfo uriInfo) {
MyPOJO pojo = ...
Annotation[] responseAnnotations = new Annotation[]{MyDetailView.Factory.get()};
return Response.ok().entity(pojo, responseAnnotations).build();
}
}
After the first test, I tried to use the SelectableEntityFilteringFeature to allow the client to ask for specific fields in the detail, so I changed the ApplicationConfig
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
....
register(EntityFilteringFeature.class);
register(SelectableEntityFilteringFeature.class);
property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "fields");
}
and I've add the "fields" QueryParam to the Resource getItem() method...
#GET
#Path("/{id}")
public Response getDetail(#PathParam({id}) String id,
#QueryParam("fields") String fields,
#Context UriInfo uriInfo) {
....
But as long as I registered the SelectableEntityFilteringFeature class, the EntityFilteringFeature class stopped working. I tried to add "fields" parameter to one of the Resource methods, it worked perfectly. But the MyDetailAnnotation was completely useless.
I tried to register it using a DynamicFeature
public class MyDynamicFeature implements DynamicFeature {
#Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
if ("MyResource".equals(resourceInfo.getResourceClass().getSimpleName())
&& "getItem".equals(resourceInfo.getResourceMethod().getName())) {
//*** IS THE CORRECT WAY TO BIND A FEATURE TO A METHOD? ***
//
context.register(SelectableEntityFilteringFeature.class);
context.property(SelectableEntityFilteringFeature.QUERY_PARAM_NAME, "fields");
}
}
Now the questions:
1) Why registering both the SelectableEntityFilteringFeature feature breaks the EntityFilteringFeature?
2) What is the correct way to bind a feature to a method with the DynamicFeature interface?
Thanks in advance.
This is my first post to Stack Overflow, I hope it was written complaining the rules.
Short answer: you can't. It appears to be a bug as of 2.25.1 and up to 2.26(that I tested with). https://github.com/jersey/jersey/issues/3523
SelectableEntityFilteringFeature implictily registers EntityFilteringFeature (As mentioned here). So I don't see a need to add this.
Since you need Annotation based filtering, you can exclude registering SelectableEntityFilteringFeature.
You can just do,
// Set entity-filtering scope via configuration.
.property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new Annotation[] {MyDetailView.Factory.get()})
// Register the EntityFilteringFeature.
.register(EntityFilteringFeature.class)
// Further configuration of ResourceConfig.
You can refer to this example for usage and this example for registering the filter.
So you can remove SelectableEntityFilteringFeature and try just the above mentioned way to register it.
I'm new to Eclipse e4 and I am trying to inject an object of my custom class into a Handler class like below :
public class MenuHandler {
#Inject
Test2 user;
#Execute
public void execute(MApplication app, EPartService partService, EModelService modelService) {
System.out.println(user.getUserName()); // DefaultUser
user.setUserName("anotherUser");
System.out.println(user.getUserName()); //anotherUser
}
}
#Creatable
public class Test2 {
private String userName = "DefaultUser";
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Having this code and If I launch my RCP application, and upon clicking the menu item (defined in the 'Application.e4xmi' file) my handler class ('MenuHandler') is not getting executed. Whereas if I remove the #Inject annotation from the handler class (i.e.., upon removing #Inject Test2 user; ) then the handler class is getting executed without any issues.
I think some problem exists if I have the annotation "#Inject" inside the Handler class.
Any suggestion will be greatly appreciated !
Maybe you should try to create and inject your custom object in the LifeCycleManager of your e4 application.
public class LifeCycleManager {
#PostContextCreate
public void postContextCreate(IEclipseContext context) {
final MCustomContext customContext = PersistenceUtils.load(MCustomContext.class);
context.set(MCustomContext.class, customContext);
}
}
This works fine for me.
I am creating a custom tag library using http://www.cqblueprints.com/xwiki/bin/view/Blue+Prints/Writing+A+JSP+Custom+Tag+Library to produce XSS-proof links from my custom components. I have taken this to a tag since I will need to do other bits of work and to avoid writing scriptlets on the JSP files (I have posted the code at the end).
I wanted to use the XSSAPI from my Java class, but looking at the javadoc for XSSAPI I see that it's an interface; when using it in a JSP file it's an object that is initialized invoking <cq:defineObjects/>.
Does anyone have any ideas on how to do this? There is a method in the XSSAPI class called getRequestSpecificAPI(slingRequest) but it's not static, and I have run out of ideas right now.
#JspTag
public class FixInternalLinkTag extends CqSimpleTagSupport {
private String pathToPage;
#Override
public void doTag() throws JspException, IOException {
XSSAPI xssAPI; // ToDo how to get a reference to this?
urlPointingToPage = xssAPI.getValidHref(urlPointingToPage);
getJspWriter().write(urlPointingToPage);
}
public String getPathToPage() {
return pathToPage;
}
#JspTagAttribute(required = true, rtexprvalue = true)
public void setPathToPage(String pathToPage) {
this.pathToPage = pathToPage;
}
}
If you make your tag class an osgi service
#Component(immediate = true, metatype = true, description = "User Group Finder")
#Service
public class MyClass { ...
you can then use
#Reference
XSSAPI xssapi;
to pull in the implementation of XSSAPI. Then you can use it
xssapi.getRequestSpecificAPI(slingRequest);
I am using GWT 2.5.0
My intent was to create an editor hierarchy which binds to a ParentBean object. The ParentBean contains a List<Group>, and the Group bean has a List<ChildBean> and List<Group>. From the Editor tutorials I have found, it seemed simple enough to create an editor which contains a ListEditor as one of its sub-editors. But the parent editor never seems to properly initialize the sub ListEditor.
Here is an explanation of how I attempted to do this.
From the code below, I created a ParentBeanEditor which is composed of one other editor, GroupListEditor.
The GroupListEditor implements IsEditor<ListEditor<Group, GroupEditor>>.
Then, the GroupEditor contains a GroupListEditor subeditor and a ChildBeanEditor.
I initialized the ParentBeanEditor with a ParentBean which contained a list of Group objects, but no GroupEditor was ever constructed for any of the Group objects. I put break points in the EditorSource<GroupEditor>.create(int) method to verify that GroupEditors were being created for each Group in the ParentBean, but the break point was never hit (the ListEditor was not constructing editors).
I expected that the GroupListEditor would be initialized since it was a subeditor of ParentBeanEditor. Neither the list nor the editor chain was set in the GroupListEditor. I tried to set the list of the GroupListEditor subeditor directly in ParentBeanEditor by having it extend ValueAwareEditor<ParentBean>. Doing this, the break point I mentioned above was hit, and the GroupListEditor tried to attach a GroupEditor to the editor chain. But the editor chain was never set, and a NPE is thrown in ListEditorWrapper line 95.
Example
Here is the example where the GroupListEditor is not initializing as expected. The EditorChain is never set, and this results in a NPE being thrown in ListEditorWrapper line 95.
Data Model
public interface ParentBean {
...
List<Group> getGroups();
}
public interface Group {
...
List<ChildBean> getChildBeans();
List<Group> getGroups();
}
public interface ChildBean {
// ChildType is an enum
ChildType getChildType();
}
Editors
The ParentBean Editor
public class ParentBeanEditor extends Composite implements ValueAwareEditor<ParentBean> {
interface ParentBeanEditorUiBinder extends UiBinder<Widget, ParentBeanEditor> {
}
private static ParentBeanEditorUiBinder BINDER = GWT.create(ParentBeanEditorUiBinder.class);
#Path("groups")
#UiField
GroupListEditor groupsEditor;
public ParentBeanEditor() {
initWidget(BINDER.createAndBindUi(this));
}
#Override
public void setDelegate(EditorDelegate<ParentBean> delegate) {}
#Override
public void flush() {}
#Override
public void onPropertyChange(String... paths) {}
#Override
public void setValue(ParentBean value) {
groupsEditor.asEditor().setValue(value.getGroups());
}
}
GroupListEditor
public class GroupListEditor extends Composite implements IsEditor<ListEditor<Group, GroupEditor>>{
interface GroupListEditorUiBinder extends UiBinder<VerticalLayoutContainer, TemplateGroupListEditor> {
}
private static GroupListEditorUiBinder BINDER = GWT.create(GroupListEditorUiBinder.class);
private class GroupEditorSource extends EditorSource<GroupEditor> {
private final GroupListEditor GroupListEditor;
public GroupEditorSource(GroupListEditor GroupListEditor) {
this.GroupListEditor = GroupListEditor;
}
#Override
public GroupEditor create(int index) {
GroupEditor subEditor = new GroupEditor();
GroupListEditor.getGroupsContainer().insert(subEditor, index);
return subEditor;
}
#Override
public void dispose(GroupEditor subEditor){
subEditor.removeFromParent();
}
#Override
public void setIndex(GroupEditor editor, int index){
GroupListEditor.getGroupsContainer().insert(editor, index);
}
}
private final ListEditor<Group, GroupEditor> editor = ListEditor.of(new GroupEditorSource(this));
#UiField
VerticalLayoutContainer groupsContainer;
public GroupListEditor() {
initWidget(BINDER.createAndBindUi(this));
}
public InsertResizeContainer getGroupsContainer() {
return groupsContainer;
}
#Override
public ListEditor<Group, GroupEditor> asEditor() {
return editor;
}
}
GroupEditor
public class GroupEditor extends Composite implements ValueAwareEditor<Group> {
interface GroupEditorUiBinder extends UiBinder<Widget, GroupEditor> {}
private static GroupEditorUiBinder BINDER = GWT.create(GroupEditorUiBinder.class);
#Ignore
#UiField
FieldSet groupField;
#UiField
#Path("childBeans")
ChildBeanListEditor childBeansEditor;
#UiField
#Path("groups")
GroupListEditor groupsEditor;
public GroupEditor() {
initWidget(BINDER.createAndBindUi(this));
}
#Override
public void setDelegate(EditorDelegate<Group> delegate) {}
#Override
public void flush() { }
#Override
public void onPropertyChange(String... paths) {}
#Override
public void setValue(Group value) {
// When the value is set, update the FieldSet header text
groupField.setHeadingText(value.getLabel());
groupsEditor.asEditor().setValue(value.getGroups());
childBeansEditor.asEditor().setValue(value.getChildBeans());
}
}
The ChildBeanListEditor will be using the polymorphic editor methodology mention here. Meaning that a specific leafeditor is attached to the editor chain based off the value of the ChildBean.getType() enum. However, I am not showing that code since I am unable to get the GroupListEditor to properly initialize.
Two concerns about your code:
Why is ParentBeanEditor.setValue feeding data to its child? It appears from this that this was a way to work around the fact that the GroupListEditor was not getting data. This should not be necessary, and may be causing your NPE by wiring up a subeditor before it is time.
Then, assuming this, it seems to follow that the GroupListEditor isn't getting data or a chain. The lack of these suggests that the Editor Framework isn't aware of it. All the basic wiring looks correct, except for one thing: Where is your EditorDriver?
If you are trying to use the editor framework by just invoking parentBeanEditor.setValue and do not have a driver, you are missing most of the key features of this tool. You should be able to ask the driver to do this work for you, and not not to call your own setValue methods throughout the tree.
A quick test - try breaking something in such a way that shouldn't compile. This would include changing the #Path annotation to something like #Path("doesnt.exist"), and trying to run the app. You should get a rebind error, as there is no such path. If you do not get this, you definitely need to be creating and user a driver.
First, try driver itself:
It isn't quite clear from your code what kind of models you are using, so I'll assume that the SimpleBeanEditorDriver will suffice for you - the other main option is the RequestFactoryEditorDriver, but it isn't actually necessary to use the RequestFactoryEditorDriver even if you use RequestFactory.
The Driver is generic on two things: The bean type you intend to edit, and the editor type that will be responsible for it. It uses these generic arguments to traverse both objects and generate code required to bind the data. Yours will likely look like this:
public interface Driver extends
SimpleBeanEditorDriver<ParentBean, ParentBeanEditor> { }
We declare these just like UiBinder interfaces - just enough details to let the code generator look around and wire up essentials. Now that we have the type, we create an instance. This might be created in your view, but may still be owned and controlled by some presenter logic. Note that this is not like uibinder - we cannot keep a static instance, since each one is wired directly to a specific editor instance.
Two steps here - create the driver, and initialize it to a given editor instance (and all sub-editors, which will be automatic):
ParentBeanEditor editor = ...;
Driver driver = GWT.create(Driver.class);
driver.initialize(editor);
Next we bind data by passing it to the driver - it is its responsibility to pass sub-objects to each sub-editor's setValue method, as well as wiring up the editor chain required by the ListEditor.
driver.edit(parentInstance);
Now the user can view or edit the object, as your application requirement works. When editing is complete (say they click the Save button), we can flush all changes from the editors back into the instance (and note that we are still using the same driver instance, still holding that specific editor instance):
ParentBean instance = driver.flush();
Note that we also could have just invoked driver.flush() and reused the earlier reference to parentInstance - its the same thing.
Assuming this has all made sense so far, there is some cleanup that can be done - ParentBeanEditor isn't really using the ValueAwareEditor methods, so they can be removed:
public class ParentBeanEditor extends Composite implements Editor<ParentBean> {
interface ParentBeanEditorUiBinder extends UiBinder<Widget, ParentBeanEditor> {
}
private static ParentBeanEditorUiBinder BINDER = GWT.create(ParentBeanEditorUiBinder.class);
#Path("groups")
#UiField
GroupListEditor groupsEditor;
public ParentBeanEditor() {
initWidget(BINDER.createAndBindUi(this));
}
}
Observe that we still implement Editor<ParentBean> - this allows the driver generics to make sense, and declares that we have fields that might themselves be sub-editors to be wired up. Also: it turns out that the #Path annotation here is unnecessary - any field/method with the same name as the property (getGroups()/setGroups() ==> groups) or the name of the property plus 'Editor' (groupsEditor). If the editor contains a field that is an editor but doesn't map to a property in the bean, you'll get an error. If you actually did this on purpose (say, a text box for searching, not for data entry), you can tag it with #Ignore.