Struts2 JSON Plugin With Annotations - json

I have a Struts2 Action Class configured via annotations. All of the "normal" methods that are annotated with #Action work fine.
However, I need to add a method into the action that returns JSON.
Here is a trimmed down version of my class (dao autowired with Spring):
#Namespace("featureClass")
// define success and input actions for class here
public class FeatureClassAction extends ActionSupport {
FeatureClassDao featureClassDao;
#Autowired
public setFeatureClassDao(FeatureClassDeao featureClassDao) {
this.featureClassDao = featureClassDao;
}
List<FeatureClass> featureClasses;
// snip normal actions
#Action("/featureClassesJSON")
#JSON
public String getFeatureClassesJSON() throws Exception {
featureClasses = featureClassDao.getAll();
return SUCCESS;
}
}
Can anyone assist? If I have to go the struts.xml route, that means moving all of my other actions (which work fine) into it.

I figured I would share the answer, since anyone else with the same problem would likely also face the silence.
I created two actions: FeatureClassAction and FeatureClassJsonAction. FeatureClassAction was annotated as such:
#ParentPackage("struts-default")
#Namespace("/featureClass")
public class FeatureClassAction extends ActionSupport {
FeatureClassJsonAction is annotated like this:
#ParentPackage("json-default")
#Namespace("/featureClass")
public class FeatureClassJsonAction extends ActionSupport {
The method in the JSON Action was annotated like this:
#Action(value="featureClassesJson", results = {
#Result(name="success", type="json")
})
public String getFeatureClassesJSON() throws Exception {
Hope it helps someone.

Related

Angular casting http get response but not nested property

I am returning a list of products of type ListProd in my Spring Boot controller, and such object has a nested property of type List<Product> ... something like this:
public class Product implements Serializable {
int codProdct;
String dsc;
public Product(){};
// plus getters and setters (omitted for simplicity)
}
public class ListProd implements Serializable {
int codList;
List<Product> products;
public ListProd(){};
// also here getters and setters
}
and in my angular project I have the next analogoust entities:
export class Product {
public codProduct:number;
public dsc:string;
constructor(){
codProduct=null; //just for completness
dsc='';
}
}
export class ListProd {
public codList:number;
public products:Product[];
constructor(){
this.codList=null; //just for completness
this.products=null;
}
}
I'm sending a ListProd object through my Spring controller and Angular gets such an object correctly and assigns the type also correctly:
return this.http.get<ListProd>(this.apiUrl + "/getListProds", httpOptions);
but ... it is only casting correctly the parent object, when I check the type of the 'products' object (which is recived correctly, only untyped) y get type: Object
I tried to make it a Products[] in my ListProd class in java, but i get the same result. I don't know much about the 'magic' Angular does to assign those types properly, am I missing something important here? Is there a chance to force the casting on the Angular side?
Thanks in advance.
Well, if ListProd is supposed to hold array of Product[] there is a typo here.
public products:Product[];
Not knowing full extent why you use class over an interface I would advise you also to go over this. Maybe there is a reason but for being able to strong type simple interface would be better. https://www.javatpoint.com/typescript-class-vs-interface

Spring controller maps to anything under a given address

I have a Spring controller that I want to handle mapping for anything under "/location" like "/location/Seattle" for a website and return the appropriate web page. Here is what I have currently
#Controller
public class WeatherController {
#RequestMapping("/location/?")
public String getWeatherData() throws Exception {
return "weather";
}
}
How can I do this? If I am going about it the wrong way please tell me. Right now I just get an error when trying to access anything besides "/location".
Your class should look like this.
#Controller
public class WeatherController {
#RequestMapping(value = "/location/{city}", method = RequestMethod.GET)
public String getWeatherData(#PathVariable("city") String city){
// implement your logic in here using city variable
return "weather";
}

Does Mockito support #Any #Inject Instance<> interface?

I have a init() method that use injected private instance<>. How can I test this class using JUnit or Mockito? I tried to make some fake class and add them to a list and set this list to my private field but I have this error
java.lang.IllegalArgumentException: Can not set javax.enterprise.inject.Instance field ......
MyClass is:
#Singleton
#Startup
public class HandlerManager {
#Any
#Inject
private Instance<RollbackHandler<RollbackData>> handlers;
private RollbackHandler<RollbackData> rollbackHandler;
#PostConstruct
public void init() {
for (RollbackHandler<RollbackData> bean : handlers) {
//do something
}
}
}
Any annotation is not processed by frameworks, unless you use custom work. you will have to define all those dependencies as mocks in your test using #Mock and call injectMocks() from before test methods such as setup(). It is a multi part problem.
Use constructor injection, field injection is evil. you still will be able to annotate your constructor with #Inject.
when(provider.iterator()).thenReturn(list.iterator);
works for me.
You can create a temporary list with concrete implementations of the RollbackHandler, and mock the iterator() method of your Instance<RollbackHandler<RollbackData>> object so that it returns the iterator of the temporary list.
Example:
private void mockIterator() {
Instance<RollbackHandler<RollbackData>> handlers = mock(Instance.class);
List<RollbackHandler<RollbackData>> handlersList = Collections.singletonList(new RollbackHandlerImpl<>());
when(handlers.iterator()).thenReturn(handlersList.iterator());
}

java.util.Collection deserialization using jackson

I have a problem deserializing Collection. Please help me. Below there are 3 VO's and the first UpdateFiltersForQueueUserIdByVO is getting passed to my REST method. If you see the inside vo's are old one's and 1.4 is used to compile them and they have generic Colleciton properties. json is unable to deserialize the Collection. How can we define mixin for FilterProfileVO, FilterVO. Thanks in advance.
// This is compiled in java 1.7, wrapper vo
public class UpdateFiltersForQueueUserIdByVO {
private FilterProfileVO filterProfileVO;
}
// Below two vo's are getting compiled in java 1.4 and I can't change
public class FilterProfileVO extends ValueObject implements Serializable {
// some other variables
private Collection filterVOs;
}
public class FilterVO extends ValueObject{
private Collection filterDetailsList;
private Collection filterCodeValueColl;
}
Regarads,
GP
Issue resolved after implementing below two mixin classes. Hope this helps someone.
public interface FilterProfileVOMixin {
#JsonSerialize(as=ArrayList.class, contentAs=FilterVO.class)
#JsonDeserialize(as=ArrayList.class, contentAs=FilterVO.class)
public Collection getFilterVOs();
}
public interface FilterProfileVOMixin {
#JsonSerialize(as=ArrayList.class, contentAs=FilterVO.class)
#JsonDeserialize(as=ArrayList.class, contentAs=FilterVO.class)
public Collection getFilterVOs();
}

Any alternative to injecting Castle Windsor typed factories?

Most of my components are registered using the code-based (fluent) approach, but there is one particular component that I need to resolve differently at runtime. This is the interface and a couple of concrete implementations:-
public interface ICommsService ...
public class SerialCommsService : ICommsService ...
public class TcpCommsService : ICommsService ...
Some of our users will need the serial service while others will need the TCP service. My current solution (which works btw) is to use a typed factory and a custom component selector - the latter reads an app.config setting to determine which implementation the typed factory will resolve and return.
First the typed factory (nothing special about this):-
public interface ICommsServiceFactory
{
ICommsService Create();
void Release(ICommsService component);
}
Next, the custom component selector, which reads the fully-qualified type name from app.config (e.g. "MyApp.SomeNamespace.TcpCommsService"):-
public class CommsFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return ConfigurationManager.AppSettings["commsServiceType"];
}
}
Then the registration stuff:-
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>()
.ImplementedBy<CommsFactoryComponentSelector>());
container.Register(Component.For<ICommsFactory>()
.AsFactory(o => o.SelectedWith<CommsFactoryComponentSelector>()));
container.Register(Component.For<ICommsService>()
.ImplementedBy<SerialCommsService>().LifeStyle.Singleton);
container.Register(Component.For<ICommsService>()
.ImplementedBy<TcpCommsService>().LifeStyle.Singleton);
Finally, an example class with a dependency on ICommsService:-
public class Test
{
public Test(ICommsFactory commsFactory)
{
var commsService = commsFactory.Create();
...
}
}
As already mentioned, the above solution does work, but I don't like having to inject the factory. It would be more intuitive if I could just inject an ICommsService, and let something somewhere figure out which implementation to resolve and inject - similar to what I'm doing now but earlier in Windsor's "resolving pipeline". Is something like that possible?
You can use UsingFactoryMethod here:
container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create()));
You can inject ICommsService to any class now. ICommsServiceFactory can be a simple interface now:
interface ICommsServiceFactory
{
ICommsService Create();
}