Struts 2 get custom action anotation in interceptors - struts2

Consider below action class with three action mappings. Two of them are annotated with a custom annotation #AjaxAction
public class MyAction extends ActionSupport{
#Action("action1")
#AjaxAction //My custom anotation
public String action1(){
}
#Action("action2")
public String action2(){
}
#Action("action3")
#AjaxAction //My custom anotation
public String action3(){
}
}
In an interceptor I want to access the #AjaxAction annotation. Is there any built in support for this?!
If not can I shall read the action name with ActionContext.getContext().getName(); and save a list of ajaxAction names in interceptor as an array and compare action name with this array! any better way?!
private static final String[] AJAX_ACTIONS = new String[] {"action1", "action3"}
//in interceptor
String actionName = ActionContext.getContext().getName();
if (Arrays.asList(AJAX_ACTIONS).contains(actionName)) {
// do something
}

Here is the way
import java.lang.reflect.Method;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class YourInterceptor implements Interceptor {
#Override
public String intercept(ActionInvocation inv) throws Exception {
Class myActionClass = inv.getAction().getClass();
for (Method method : myActionClass.getMethods())
{
if(method.isAnnotationPresent(AjaxAction.class))
{
// do something
}
}
return inv.invoke();
}
}
Alternative is
import com.opensymphony.xwork2.util.AnnotationUtils;
import java.lang.reflect.Method;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class YourInterceptor implements Interceptor {
#Override
public String intercept(ActionInvocation inv) throws Exception {
AnnotationUtils myutil = new AnnotationUtils();
Class myActionClass = inv.getAction().getClass();
for (Method method : myActionClass.getMethods())
{
if(myutil.getAnnotatedMethods(myActionClass, AjaxAction.class).contains(method))
{
// do something
}
}
return inv.invoke();
}
}
Edit :
To find exact executed method.
Note: Change Namespace="/" as per your configuration in struts.xml.
import org.apache.struts2.dispatcher.Dispatcher;
ActionContext context = inv.getInvocationContext();
String executedAction=context.getName();
String executedMethod=Dispatcher.getInstance().getConfigurationManager().getConfiguration().getRuntimeConfiguration().getActionConfigs().get("/").get(executedAction).getMethodName();
if(executedMethod==null)
{
executedMethod="execute";
}
for (Method method : myActionClass.getMethods())
{
if(method.getName().equalsIgnoreCase(executedMethod) || method.isAnnotationPresent(Action.class))
{
// do something
}
}
Class myActionClass = inv.getAction().getClass();
for (Method method : myActionClass.getMethods())
{
//check whether called method has annotation?
if(method.getName().equalsIgnoreCase(executedAction) && method.isAnnotationPresent(AjaxAction.class))
{
// do something
}
}
I hope this will work.
Note: This is just a workaround I found. Better way would be possible....

Related

Polymorphism with swagger not working as expected

I am using springfox version 2.9.2 and swagger annotations 1.5.x. The ApiModel annotations support the discriminator, subTypes and parent attribute which are required to make polymorphism work but I am not seeing the correct apidocs generated to enable polymorphism.
Here is my annotated code.
#RestController
#RequestMapping("/api/vehicles")
public class VehicleController {
private static final Logger LOGGER = LoggerFactory.getLogger(VehicleController.class);
#PostMapping(consumes = {MediaType.APPLICATION_JSON_UTF8_VALUE})
void post(#RequestBody Vehicle anyVehicle) {
LOGGER.info("Vehicle : {}", anyVehicle);
}
}
#ApiModel(discriminator = "type", subTypes = {Car.class, Bike.class})
public class Vehicle {
String brand;
String type;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
#ApiModel(parent = Vehicle.class)
public class Car extends Vehicle {
int noOfDoors;
boolean powerWindows;
public int getNoOfDoors() {
return noOfDoors;
}
public void setNoOfDoors(int noOfDoors) {
this.noOfDoors = noOfDoors;
}
public boolean isPowerWindows() {
return powerWindows;
}
public void setPowerWindows(boolean powerWindows) {
this.powerWindows = powerWindows;
}
}
#ApiModel(parent = Vehicle.class)
public class Bike extends Vehicle {
boolean pillion;
public boolean isPillion() {
return pillion;
}
public void setPillion(boolean pillion) {
this.pillion = pillion;
}
}
When the docs get generated is basically shows one endpoint which handles a POST request and takes in a Vehicle as the model.
Is what I am doing here supposed to work? Can someone point me to a working example of this with SpringFox that I can look at?
Support for discriminator is not available in Swagger UI yet. You can follow these issues for status updates:
Discriminator does not switch schema
subTypes not displayed in model

Struts2 & Java8 passing parameter to action using interface default method implementation - does not work

I'm passing parameter projectId to Struts action
http://localhost:8080/app/myaction.action?projectId=100
Simple action class is defined as:
public class MyAction extends AnyStrutsAction {
private ParamReader paramReader = new ParamReader();
public ParamReader getParamReader() {
return paramReader;
}
public void setProjectId(String id) {
getParamReader().setProjectId(id);
}
public void execute()
// ...
}
}
And everything works ok (/)
Next method setProjectId is extracted to interface and implemented as Java8 default method:
public interface ParamReaderAware {
ParamReader getParamReader();
default void setProjectId(String id) {
getParamReader().setProjectId(id);
}
}
public class MyAction extends AnyStrutsAction implements ParamReaderAware {
private ParamReader paramReader = new ParamReader();
#Override
public ParamReader getParamReader() {
return paramReader;
}
public void execute()
// ...
}
}
Now calling
http://localhost:8080/app/myaction.action?projectId=100
does not set parameter projectId. The default implementation is not visible for struts
My question is:
- does Struts2 support default interface method ?
- Is there any way to do so (any struts configuration, version (currentyly im using 2.3.16) )
Why I extract method to interface.
- I want to add reading parameter feature to multiple class actions

Autofac. How to get caller class Type?

Suppose we have two classes with same constructor Injectable dependency:
public class FirstClass
{
public FirstClass(ISomeDependency someDependency)
{ }
}
public class SecondClass
{
public SecondClass(ISomeDependency someDependency)
{ }
}
Now we have a registration for ISomeDependency:
builder.Register(x =>
{
string key = GetKeyFromCurrentHttpRequest();
// if "Caller" is "FirstClass" return new Dependency(key);
// else return new Dependency("defaultKey");
}).As<ISomeDependency>();
Note: This is a simplified use case. The real scenario is much more complicated.
1. How to get "Caller" type which tryies to resolve ISomeDependency?
2. Is there a better way design for such situations?
You can use delegate factories do achieve your goal. The only drawback is the FirstClass and SecondClass cannot use ISomeDependency as parameter.
You can try this code in a console application (just add Autofac dependency).
using System;
using Autofac;
namespace test
{
class MainClass
{
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder ();
builder.RegisterType<SomeDependency>().As<ISomeDependency>();
builder.RegisterType<FirstClass>();
builder.RegisterType<SecondClass>();
var container = builder.Build();
var dummy = container.Resolve<FirstClass>();
var dummy2 = container.Resolve<SecondClass>();
}
public interface ISomeDependency
{
}
public class SomeDependency : ISomeDependency
{
public delegate ISomeDependency Factory(string value);
private readonly string _value;
public SomeDependency(string value)
{
_value = value;
Console.WriteLine("Value = " + _value);
}
}
public class FirstClass
{
private ISomeDependency _dependency;
public FirstClass(SomeDependency.Factory factory)
{
_dependency = factory.Invoke("my value");
}
}
public class SecondClass
{
private ISomeDependency _dependency;
public SecondClass(SomeDependency.Factory factory)
{
_dependency = factory.Invoke("my value 2");
}
}
}
}

Dagger - Is it possible to select a Provider based on inheritance?

At the moment I have a Base class that contains a member I would like to inject. However, I would like the concrete type of this member to depend on the Subclass being instantiated. What I am aiming for is something along these lines:
public interface StringInterface {
public String getString();
}
public class HelloStringConcrete implements StringInterface {
public String getString() {
return "Hello";
}
}
public class WorldStringConcrete implements StringInterface {
public String getString() {
return "World";
}
}
public abstract class Base {
#Inject StringInterface member;
public Base() {
// Assume access to object graph
MyObjectGraph.get().inject(this);
}
public void printSomething() {
System.out.println(member.getString());
}
}
public class SubclassHello extends Base {}
public class SubclassWorld extends Base {}
#Module(injects = {SubclassHello.class})
public class HelloModule {
#Provides StringInterface provideStringInterface() {
return new HelloStringConcrete();
}
}
#Module(injects = {SubclassWorld.class})
public class WorldModule {
#Provides StringInterface provideStringInterface() {
return new WorldStringConcrete();
}
}
So now what I would like to do is something along the lines of:
#Module(
includes = {
HelloModule.class,
WorldModule.class
}
)
public class BigModule {}
// Somewhere in another piece of code...
objectGraph = ObjectGraph.create(new BigModule());
// In yet another piece of code...
SubclassHello hello = new SubclassHello();
SubclassWorld world = new SubclassWorld();
hello.printSomething();
world.printSomething();
// Hopefully would result in :
// Hello
// World
This type of setup won't work though, because including two modules with the same provider will result in a duplicate provider error at compile time. It would be cool to see a solution to this problem without introducing #Named or #Qualifer annotations, or using scoped graph extensions via graph.plus() because these strategies necessarily introduce coupling to the subclasses
This is possible but I think the code I've attached below is more coupled than using scoped graphs or annotations. Basically you can use constructor injection to inject concrete dependencies to your
SubclassHello and SubclassWorld.
public abstract class Base {
private final StringInterface member;
public Base(StringInterface member) {
this.member = member;
}
...
}
#Module(injects = {SubclassWorld.class})
public class WorldModule {
#Provides
WorldStringConcrete provideStringInterface() {
return new WorldStringConcrete();
}
}
public class SubclassWorld extends Base {
#Inject
public SubclassWorld(WorldStringConcrete worldStringConcrete) {
super(worldStringConcrete);
}
}
#Module(injects = {SubclassHello.class})
public class HelloModule {
#Provides
HelloStringConcrete provideStringInterface() {
return new HelloStringConcrete();
}
}
public class SubclassHello extends Base {
#Inject
public SubclassHello(HelloStringConcrete helloStringConcrete) {
super(helloStringConcrete);
}
}
// Somewhere in another piece of code...
ObjectGraph objectGraph = ObjectGraph.create(new BigModule());
// In yet another piece of code...
SubclassHello hello = objectGraph.get(SubclassHello.class);
SubclassWorld world = objectGraph.get(SubclassWorld.class);
I don't think there are other solutions. How could Dagger find out which StringInterface implementations should be injected to the concrete classes?

Caused by: javax.el.MethodNotFoundException: Method not found

I couldn't see any thing.Here is my ManagedBean;
public class AralikKontrolEvent {
private String sayi;
private String mesaj="";
public String getMesaj() {
return mesaj;
}
public void setMesaj(String mesaj) {
this.mesaj = mesaj;
}
public String getSayi() {
return sayi;
}
public void setSayi(String sayi) {
this.sayi = sayi;
}
public void SayiKontrolEt(ActionEvent event){
int a = Integer.parseInt(sayi);
if(event.getComponent().getId().equals("gonder")){
if(a>10){
mesaj+="Sayı büyük";
}else{
mesaj+="Sayı küçük";
}
}
}
I called SayiKontrolEt method like below;
< h : commandButton value="Gönder" id="gonder" action="#{ake.SayiKontrolEt}"/>
But I get this error.I have looked lots of examples about jsf event.Everybody calls like I have called the method.What is the wrong which I haven't seen?
You have two options:
Remove ActionEvent from the method
Or change action to actionListener
Remove the ActionEvent argument from the method.

Resources