Can I match class that implements annotated Interface with knowledge only about annotation type? - javaagents

just like in the topic. I have my resource class :
public class HelloWorldEndpoint implements IRest {
public String sayHello()
{
return "Hello world!";
}
}
And Interface :
#Path("/helloworld")
public interface IRest {
#GET
#Path("/hello")
String sayHello();
}
Is it possible to match sayHello() from HelloWorldEndpoint using only #Path class annotation? This is very specific example of resource class implementation, but it shows that it is possible to have REST endpoint without any annotation in class.. I've tried with inheritsAnnotation() and isAnnotatedWith() but it's not working that way unfortunatly. My goal is to find all resource classes :)

Annotations of interfaces are not inherited in accordance to the Java Langauge specification. They are neither exposed by the reflection API, for example.
In order to discover the annotation, you can manually travers the class hierarchy and look for the annotation in question. This is possible by hasSuperType(isAnnotatedWith(...)). Note that this is a rather expensive matching condition.

Related

How to exclude properties from schemas using #JsonView

In Spring when a controller method is annotated with #JsonView, it returns only the
respective annotated properties of the object honoring the configuration
spring.jackson.mapper.default-view-inclusion, which is set to false by default.
// Kotlin code
abstract class Base {
lateinit var transientInternalProperty: String
}
class Main(val externalProperty: String) : Base()
#RestController
#RequestMapping("/")
class MainController {
#JsonView(Views.Public::class)
#GetMapping("/")
fun index() = Main()
}
Taking the above example, how to exclude non annotated properties on the generated
Main_Public schema. How to leave transientInternalProperty out of Main_Public without having to annotate it also?
I couldn't find anything about this in the documentation. Just this small section.
I tried to annotate the class itself with #JsonView to indicate "default view" for properties but it did not work.
To exclude properties from the generated OpenAPI sepc: prefer swagger-annotation, you #Hidden or #Schema(hidden = true)).

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

Type-safe IDs in service layer for error prevention

I'm currently writing on the business logic of an Java-application. I've splitted it into domain layer and service layer. The service layer provides interfaces which allow access on the data via data transfer objects.
The idea i've got is to make "typesafe" IDs. That could be simple described as that the method getId() doesn't return a long but instead an object of an special class which consists of the ID value and also a Class-field to determine the type which object is referred. The motivation befind this is, that I used the ID of the wrong type which lead to a difficult-to-detect error.
The ID-Class would look something like this:
public class ObjectId<T>
{
private Class<T> type;
prviate long id;
...
}
The class is then used in a DTO:
public class SomeDTO
{
public ObjectId<SomeDTO> getId(){...}
...
}
and also in the service:
public interface TheService
{
public SomeDTO getSome(ObjectId<SomeDTO> id);
...
}
I might be completly wrong, but beside some drawbacks like a more complex model it also offers the possibility to prevent such errors at the outsets.
Is it a good or a crazy idea?

Jackson 1.9.0: JsonTypeInfo for abstract class not working with Lists

Using this abstract class:
#JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
#JsonSubTypes({ #JsonSubTypes.Type(value = PostingTaskInstanceDto.class, name = "TI") })
public abstract class BasePostingDto {}
and this inherited class:
public class PostingTaskInstanceDto extends BasePostingDto {}
I get correct serialization for a single object. This works, using Spring-MVC:
#RequestMapping("/{id}")
#ResponseBody
public BasePostingDto findById(#PathVariable("id") Long id) {
return createDto(postingService.findById(id));
}
But if I retrieve a List of BasePostingDto from the remote controller, the type property is missing:
#RequestMapping("/by-user/all")
#ResponseBody
public List<BasePostingDto> findByUser() {
return createDtoList(postingService.findByUser(AuthUtils.getUser()));
}
Why is this and how can I force the type property?
Update: the type property is also included if I change List<BasePostingDto> to BasePostingDto[], however I would prefer to go with the List.
It sounds like the framework you are using (and which uses Jackson under the hood) is not passing full generics-aware type information.
I don't know how that can be fixed (it is problem with integration by framework, and not something Jackson can address), but the usual work around is for you to use sub-class of List:
public class PostingDtoList extends List<BasePostingDto> { }
and use that in signature, instead of generic type. This solves the issue because then the generic type signature is retained (since it is stored in super type declaration, and accessible via type-erased PostingDtoList class!).
In generally I think it is best to avoid using generic List and Map types as root type (and instead use POJO); partly because of problems issued (there are bigger problems when using XML for example). But it can be made to work if need be.

JAXB Unmarshal Exception

I generated some classes off of an xsd that I made from a web service response that I am calling.
I'm getting an Exception when I run a JUnit test class that reads in an InputStream from the web service call.
I'm stuck as to what the exception means, so I'm looking for some ideas on things to check:
javax.xml.bind.UnmarshalException: Unexpected element {http://bar.foo.com/bbs}:rule
I have a class in my generated classes at:
com.foo.bar.bbs.Rule
Does the Exception mean I do not have the Rule class in the proper package?
The following are some things to check:
#XmlRootElement
Check that the Rule class is annotated with #XmlRootElement:
#XmlRootElement
public class Rule {
}
#XmlElementDecl
Or that there is a corresponding #XmlElementDecl in the ObjectFactory class:
#XmlElementDecl(namespace = "http://bar.foo.com/bbs", name = "root")
public JAXBElement<Root> createCustomer(Root value) {
return new JAXBElement<BigInteger>(_ROOT_QNAME, Root.class, null, value);
}
#XmlSchema
You will also need to ensure that the namespace information is specified correctly. A package-info class was probably generated something like the following for you. Ensure the correct namespace is specified.
#XmlSchema(
namespace = "http://bar.foo.com/bbs",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.foo.bar.bbs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Alternatively you could include the namespace in the #XmlRootElement annotation:
#XmlRootElement(namespace="http://bar.foo.com/bbs")
public class Rule {
}
For more information see:
http://bdoughan.blogspot.com/2010/08/jaxb-namespaces.html
Make sure you are unmarshalling the correct type of object.