How to access XSSAPI from custom jsp Java class? - aem

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);

Related

Attribute value must be constant: #RequestMapping, java spring endpoint

Currently I am trying to reduce the boilerplate in my java spring controllers by creating an interface CRUDRestController, which creates a common set of default endpoints:
interface CRUDRestController<T, Key extends Serializable> {
//...
String getEndpoint();
#RequestMapping(value = getEndpoint() + "/{key}", method = RequestMethod.GET)
default T get(#PathVariable("key") String key) {
return getRepository().findOne(stringToKey(key));
}
//...
}
The problem is that the above code does not compile since value = getEndpoint() + "/{key}" is supposedly not a compile time constant. In reality every controller's implementation of getEndpoint() is something like this:
#Override
public String getEndpoint() {
return "/clients";
}
This is clearly known at compile time, however I have no way of telling this to spring. Any ideas?
Maybe that will help you:
interface CRUDRestController<T, Key extends Serializable> {
#RequestMapping(value = "/{key}", method = RequestMethod.GET)
default T get(#PathVariable("key") String key) {
return getRepository().findOne(stringToKey(key));
}
}
and the implementation:
#RequestMapping("/clients")
public class ClientController implements CRUDRestController<Client, ClientKey> {
//...
}
This is a Java annotations restriction. All values passed to it must be compile time constants.
The value is clearly not known at compile time even if you would call a static method returning a static final.

Problems when using EntityFilteringFeature and SelectableEntityFilteringFeature with Jersey 2

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.

Jbehave get Story name inside #BeforeStory

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

AspectJ - Creating a global Logger field using an Inter-Type Declaration

I'd like to create an Inter-Type declaration that declares a (static final) Logger instance inside each class.
The constructor should be passed the enclosing class Klazz.class value:
#Aspect
public class LoggerAspect {
public interface Logger {
}
public static class LoggerImpl implements Logger {
private static final Logger logger =
new Logger(thisJoinPoint.getTarget().getClass()/*.getName()*/);
}
#DeclareParents(value="com.my.api..*",defaultImpl=LoggerImpl.class)
private Logger implementedInterface;
}
I wrote the above solution, however I'm unable to use thisJoinPoint outside of an AspectJ advice.
If the Logger default implementation is applied to some class Klazz, how can I modify the above code to successfully pass Klazz.class to the Logger constructor?
You can declare a static member on any single class via inter-type declaration:
public aspect LoggingAspect {
static Logger MyClass.someField = Logger.getLogger(MyClass.class.getName());
}
But this is not very flexible because you need to do it for each single class. I just wanted to mention it.
In order to add something which is not technically but effectively a static member to a class, just use per-type association for your logging aspect:
public aspect LoggingAspect
pertypewithin(org.foo..*) // per-type association
{
Logger logger;
after() : staticinitialization(*) { // run 1x after class-loading
logger = Logger.getLogger(
getWithinTypeName() // type associated with aspect instance
);
}
pointcut logged() : // what to log, e.g. public methods
execution(public * *(..)); // (pointcut could also be abstract
// and refined in sub-aspects)
before() : logged() {
logger.log(...); // logging action
}
}
An example similar to this one - it is a common pattern - can be found in Ramnivas Laddad's excellent book AspectJ in action (2nd edition), chapter 6.2.4. It is also mentioned in the AspectJ documentation.
This answer gives the correct solution, posted below for convenience. Additionally it uses AspectJ annotations which is the preferred notation nowadays.
The developers recently added the annotation API, I presume with the intention of standardising the markup as many other popular libraries like Spring are also doing.
#Aspect("pertypewithin(com.something.*))")
public abstract class TraceAspect {
Logger logger;
#Pointcut
public abstract void traced();
#Pointcut("staticinitialization(*)")
public void staticInit() {
}
#After(value = "staticInit()")
public void initLogger(JoinPoint.StaticPart jps) {
logger = Logger.getLogger(jps.getSignature().getDeclaringTypeName());
}
#Before(value = "traced()")
public void traceThatOne(JoinPoint.StaticPart jps) {
logger.log(jps.getSignature().getName());
}
}

Instance variable in Stripes

I'm trying to find a way to create an instance variable within the Stripes application context.
Something that i would do in the init() method of a Servlet while using hand-coded servlets.
The problem is that since an instance of the ActionBean is created each time the application is accessed, the variable in the actionBean is created multiple time.
I have tried to get some reasonable place withing Stripes trying to call the ServletContext via ActionBeanContext.getServletContext(), but from there there is no way to access the init() method and write some code in it.
Do you have any suggestions?
The ActionBeanContext is also Stripes application context. This context can be customized and can contain whatever you want. Some example code:
package my.app;
public class CustomActionBeanContext extends ActionBeanContext {
public CustomActionBeanContext() {
super();
}
public MyObject getMyObject() {
return (MyObject) getServletContext().getAttribute(“myObject”);
}
// Alternative solution without ServletContextListner
private static MyObject2 myObject2;
static {
myObject2 = new MyObject2();
}
public MyObject2 getMyObject2() {
return myObject2;
}
}
To let the Stripes context factory know you want to use a custom ActionBeanContext you need to add an init-param to the Stripes filter in the web.xml:
<init-param>
<param-name>ActionBeanContext.Class</param-name>
<param-value>my.app.CustomActionBeanContext</param-value>
</init-param>
You can initialize your object at server start by adding a SerlvetContextListener:
Public class MyServletContextListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("myObject", new MyObject());
}
Example ActionBean:
public class MyAction implements ActionBean {
private CustomActionBeanContext context;
#Override
public CustomActionBeanContext getContext() {
return context;
}
#Override
public void setContext(ActionBeanContext context) {
this.context = (CustomActionBeanContext) context;
}
#DefaultHandler
public Resolution view() {
MyObject myObject = getContext().getMyObject();
// doing something usefull with it..
}
}
An alternative solution, in my opinion a superiour solution, is to use a dependency injection framework for injecting the (singleton) objects into your actionbeans. See Stripes configuration example here: Injecting Stripes ActionBeans with Guice DI
Not a Stripes-specific way, but using the standard Servlet API you'd implement ServletContextListener and do the job in contextInitialized() method. If you register it as <listener> in web.xml (or when you're already on Java EE 6, annotate using #WebListener), then it'll run during webapp's startup.
#Override
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("somename", new SomeObject());
}
This way it's available in EL by ${somename} and in all action beans by ServletContext#getAttribute().
#JBoy, You have to specify your implementation of ServletContextListner in the web.xml like below
<listner>
<listner-class>
www.test.com.MyListner
</listner-class>
</listner>
Thanks KDeveloper for his advice. I was also searching for the solution. I found the information from his blog
There is one more method I have found out. For that you have to subclass the "RuntimeConfiguration" class
public class MyConfiguration extends RuntimeConfiguration {
#Override
public void init() {
getServletContext.setAttribute("myObject",new MyObject);
super.init();
}
}
After that in the web.xml specify the above configuration.
<init-param>
<param-name>Configuration.Class</param-name>
<param-value>www.test.com.MyConfiguration</param-value>
</init-param>
You also have to subclass the ActionBeanContext as KDeveloper said; to get the object in ActionBeans
This is my finding. I found out it is working. But I don't know whether it has any side effects. If it has any; please comment..