Is it possible to add annotations to static factorymetods with lombok - java

If I create a class like
#Value
#AllArgsConstructor(staticName = "of", onConstructor = #__(#JsonCreator))
public class Test {
String value;
}
The onConstructor properties is added to the constructor (which makes sense). However I need to add an annotations to the factory metod. Is this possible?
My root problem is trying to make
{
"test": 2018
}
deserialize to:
SomeJavaClass:
private final Test test
This doesn't work because of the ConstructorProperties.

Putting the annotation on the static factory method would be the most reasonable thing to do when both staticName and onConstructor are set. In that case, the regular constructor becomes private and, thus, cannot be used from elsewhere (except for ugly reflection tricks). Therefore, annotations only make sense on the static factory method in most cases.
However, this is not Lombok's current behavior, and there is no way to configure Lombok differently. I suggest you create a feature request at GitHub.
However, be aware that the onX feature is an experimental feature, so this feature request may be declined or deferred.

Related

Using Jackson Mixins to selectively ignore only provided properties

I have the following situation:
public class A {
private String someProperty;
private String anotherProperty;
public A() {}
// getter/setter
An ObjectMapper configuration as follows (enabled by default, but worth noting to get the point of the question across):
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
and an input JSON that looks as follows:
{
"someProperty": "someValue",
"anotherProperty":"anotherValue",
"unwantedProperty":"unwantedValue"
}
When deserializing this JSON using objectMapper.readValue(bytes, A.class), as expected, it gives me an exception:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "unwantedProperty"
Now, what I want to do, is the following:
Only deserialize properties that are explicitly provided by A.class
Use a MixIn to ignore all unwanted, known properties. So for example, I know that unwantedProperty is part of the JSON, but I don't need it, so I want to ignore it.
Still raise an UnrecognizedPropertyException if a new, unknown property suddenly appears in my JSON.
The reason that I wish to use something like a MixIn class for this is that in reality, the input JSON has several dozens of fields. I would prefer not to clutter my A.class with dozens and dozens of unused properties with #JsonIgnore on them, so that it only contains the fields that I really want. If a new property unexpectedly does come along, I want to be forced to have a look at it.
I thought that I could allow this behaviour by using a MixIn as follows:
public abstract class AMixIn {
#JsonIgnore private String unwantedProperty;
together with:
objectMapper.addMixIn(A.class, AMixIn.class);
but this seemingly has no effect. I've also tried creating getters in AMixIn and giving those #JsonIgnore, but this also has no result.
Am I using MixIns incorrectly here? Is what I'm trying to do even possible (as described in the 3 points above)? Or, is there a better way to do this?
I've tried searching, but my use case is a bit esoteric, so I haven't had much luck.
Answer to question 1:
You can instruct Jackson to ignore unknown properties.
I tend to configure the ObjectMapper to ignore them,
here is some sample code:
private ObjectMapper mapper;
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
// This matches the Fuse Mapper configuration.
builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
mapper = builder.build();
You can also annotate the class to ignore unknown properties.
Here is some sample code:
#jsonignoreproperties(ignoreunknown = true)
public class A
{
...
Note about question 2:
In order for the use-mixin-to-ignore-fields-in-json strategy to work,
the fields to be ignored must exist in the class.
In your case,
this means that class A must have a field "unwantedProperty" for the mixin to work correctly.
Direction to solve questions 2 and 3
You cannot use the MixIn feature of Jackson to solve either
question 2 or question 3.
Instead,
you will need to write a custom deserializer.
I suggest that you also use a custom Jackson annotation
that configures a list of ignored-unrecognized-fields
and have your custom deserializer only throw the exception
for unrecognized fields that are not part of the
ignored-unrecognized-fields list.
Well, shows how well I can search; as always, Jackson provides some way of doing whatever needs doing. In case it might help someone else:
There exists the #JsonIgnoreProperties annotation which, in addition to the ignoreUnknown property (that I already knew), supports a list of properties (via value()) to ignore during de-/serialization (which I did not know).
This is not quite the same as the intended solution above, but having these properties inside of #JsonIgnoreProperties({ ... }) in the class header instead of the class body is a good enough compromise for me.
So, the solution would be:
#JsonIgnoreProperties({"unwantedProperty"})
public class A {
// same as above...
}
Still, if there is a MixIn solution which can completely decouple these things, I'd still like to see it. I'll accept my own answer if nothing comes up in a few days.

How can I get all methods which are called by a testMethod? (Java, TestNG, IAnnotationTransformer)

I'm currently using IAnnotationTransformer to exclude all tests listed in an XML which contain a particular string in their name, for example:
#Override
#SuppressWarnings("rawtypes")
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
if(testMethod.getName().contains("StringGoesHere")){
annotation.setEnabled(false);
}
This works perfectly well, however due to the naming convention of my tests, and the vast amount of tests which I need to exclude, the ideal solution would be to find a way to exclude the test if it calls upon a particular method. For example, I want to exclude all tests which call upon the method .clickUserSettings() shown below:
#Test
public void editUserDetailsOnStackOverflow() {
final StackOverflow so = stackOverflow.loginAsMe()
.clickUserSettings()
.changeUserEmail()
.clickSave()
.assertChangeSuccessful();
}
Does anyone know how I might be able to achieve this? I feel like I've explored all other avenues (classes, packages, testMethods, groups, xml, etc) And the reason it has to be done in this way is because I currently have 40,000 tests (15,000 of which will likely be excluded depending on the browserMode variable set by the tester) This is the general idea I was hoping to achieve:
#Override
#SuppressWarnings("rawtypes")
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
if(testMethod.getAllCalledMethods.contains(".clickUserSettings()")){
annotation.setEnabled(false);
}
If this can be done it will solve my issue,
Cheers
This is not possible with TestNG. TestNG has visibility only to the methods that are annotated with its annotations and its not aware of the code path that a TestNG method traverses during its course of execution. [ Here I am assuming that the method clickUserSettings() is a utility method that your #Test methods perhaps call into, as part of its execution ]
So you have a couple of options
Resort to using groups wherein all methods that call into clickUserSettings() as part of a particular group and then exclude that group from execution.
Create your own custom annotation, annotate all methods that invoke clickUserSettings() using this annotation, and then modify your current AnnotationTransformer to look for this annotation at either the method level or at the class level.

Can I use some kind of assisted Inject with Dagger?

With Google Guice or Gin I can specify parameter with are not controlled by the dependency injection framework:
class SomeEditor {
#Inject
public SomeEditor(SomeClassA a, #Assisted("stage") SomeClassB b) {
}
}
The assisted parameter stage is specified at the time an instance of SomeEditor is created.
The instance of SomeClassA is taken from the object graph and the instance of SomeClassB is taken from the caller at runtime.
Is there a similar way of doing this in Dagger?
UPDATE: As of Dagger 2.31 from January 2021, Dagger now natively supports assisted injection, which is recommended over the Square and Auto options. (Those other options still work, but may require extra setup compared to the native option.)
class SomeEditor {
#AssistedInject public SomeEditor(
SomeClassA a, #Assisted SomeClassB b) {
// ...
}
}
#AssistedFactory interface SomeEditorFactory {
SomeEditor create(SomeClassB b);
}
(original answer)
Because factories are a separate type of boilerplate to optimize away (see mailing list discussion here), Dagger leaves it to a sister project, AutoFactory. This provides the "assisted injection" functionality Guice offers via FactoryModuleBuilder, but with some extra benefits:
You can keep using AutoFactory with Guice or Dagger or any other JSR-330 dependency injection framework, so you can keep using AutoFactory even if you switch between them.
Because AutoFactory generates code, you don't need to write an interface to represent the constructor: AutoFactory will write a brand new type for you to compile against. (You can also specify an interface to implement, if you'd prefer, or if you're migrating from Guice.)
Because all the type inspection happens at compile-time, it produces plain old Java, which doesn't have any slowness due to reflection and which works well with debuggers and optimizers. This makes the Auto library particularly useful for Android development.
Example, pulled from AutoFactory's README, which will produce a SomeClassFactory with providedDepA in an #Inject-annotated constructor and depB in a create method:
#AutoFactory
final class SomeClass {
private final String providedDepA;
private final String depB;
SomeClass(#Provided #AQualifier String providedDepA, String depB) {
this.providedDepA = providedDepA;
this.depB = depB;
}
// …
}
Just like #xsveda, I also wrote an answer about this in this other question, which I'll also reproduce here.
Today, for assisted injection with Dagger you probably want to use AssistedInject. I wrote about it in this blogpost, but I'll add a full example here to make things easier.
First thing you need are the dependencies:
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
Then here's how it can look like:
class ImageDownloader #AssistedInject constructor(
private val httpClient: HttpClient,
private val executorService: ExecutorService,
#Assisted private val imageUrl: URL,
#Assisted private val callback: ImageCallback
) {
#AssistedInject.Factory
interface Factory {
fun create(imageUrl: URL, callback: ImageCallback): ImageDownloader
}
}
First thing is that instead of annotating the constructor with #Inject, we annotate it with #AssistedInject. Then we annotate the parameters that will have to go through the factory, which is the opposite of what AutoFactory expects. Finally, we need an inner factory interface annotated with #AssistedInject.Factory that has a single method that receives the assisted parameters and returns the instance we're interested in.
Unfortunately, we still have an extra step here:
#AssistedModule
#Module(includes = [AssistedInject_AssistedInjectModule::class])
interface AssistedInjectModule
We don't necessarily need a dedicated module for it, even though that's a valid option. But we can also have those annotations in another module that is already installed in the component. The nice thing here is that we only need to do it once, and after that any factory will automatically become part of the graph.
With that, you can basically inject the factory and ask for your object as you'd normally do.
Yes, please check this Square project: square/AssistedInject
Currently it is not in 1.0 yet for purpose. They wait until Dagger will introduce a public API for registering those generated Module classes automatically - see this issue. With that you won't have to reference them in your Dagger code as in this example from README:
#AssistedModule
#Module(includes = AssistedInject_PresenterModule.class)
abstract class PresenterModule {}

Unit testing JSR-330 injected objects

I have previously used Spring DI, and one of the benefits I perceive is that I can test my Spring bean classes without involving Spring (imports omitted for brevity):
public class Foo {
private String field;
public void setField(String field) { this.field = field; }
public String getField() { return field; }
}
public class TestFoo {
#Test
public void test_field_is_set() {
Foo foo = new Foo();
foo.setField("Bar");
assertEquals("Bar", foo.getField());
}
}
Now I am experimenting with JSR-330, which means not explicitly writing setters.
I'm using Hk2 so far, purely because of some anecdotal stuff about Jersey being tied to Hk2, and making it difficult to co-habit with other JSR-330 implementations.
public class Foo {
#Inject
private String field;
}
I half expected some magic to happen, whereby the #Inject annotation caused a setter to become available, but this is not the case:
Foo foo = new Foo();
foo.setField("Bar"); // method setField(String) is undefined for the type Foo
How can I (conveniently) test this kind of annotated class without invoking a framework?
Failing that, how can I invoke a framework in a portable way (i.e. without tightly coupling my test code to Hk2, Guice, etc.)
Failing that, what's a typical, clean way to test classes annotated in this way?
Simplest is to make the fields package-private (instead of private), then in the test, set them directly. (That works if the test is in the same package)
public class Foo {
#Inject
String field;
}
Foo foo = new Foo();
foo.field = "bar";
This has the advantage of avoiding reflection so it's safe for refactoring.
The field injection approach you mentioned is actually the typical Spring style; many programmers don't write setters for private injected fields at all. Spring (with #Autowired or #Inject) and JSR-330 containers usually inject fields using direct field reflection rather than setters.
Because of this, if you don't want to use any DI framework, you could write the necessary reflection code into your unit tests yourself, but this seems like overkill just to avoid a test dependency; after all, the point of using #Inject is that you're coding to an interface, and you don't avoid using the JVM to avoid coupling to it.
The usual approach for testing this sort of class is to set up a test context for whatever container you prefer and run the unit tests in that context. If you're using Spring, you'd put an applicationContext-test.xml file or TestConfig class in your src/test/ directory (or equivalent), and if you're using Guice, you'd write a module to wire up mocks or test datasets.
It turns out that frameworks relying on private/protected field access are not so uncommon. Hibernate, JPA, several JSR-330 implementations, including Spring itself, all do it.
Spring's spring-test package provides a ReflectionTestUtils class containing static methods for accessing these fields.
Using this one can test the class in the question thus:
import static org.springframework.test.util.ReflectionTestUtils.*;
...
#Test
public void testUsingSpringReflectionTestUtils() {
Foo foo = new Foo();
setField(foo, "field", "Bar");
assertEquals("Bar", foo.getField());
}
You need spring-test and spring-core in your test classpath for this to work, but it doesn't add a dependency on Spring for your production code.
(Comments welcome about alternative implementations of the same principle welcome. I don't think it's worth rolling one's own, however simple it would be, given that Spring has a good implementation.)
Give "needle" a try: http://needle.spree.de/overview
needle is an DI-test-framework that only simulates the container behavior, making unit tests real simple.

Configuration class - best practice with Guice

Background: I'm using Google Guice and so it's easier to pass through the configuration class but I think this is not the best way.
I have a configuration class which stores some paths:
class Configuration{
String getHomePath();
String getUserPath();
}
Also I have a class "a" which needs the "homepath" and a class "b" which needs the "userpath".
Is it better to pass the configuration class through the constructor of class a and b or only pass through the specific path?
If you're really using Guice correctly all your configuration like this should appear in modules' configure method. So:
Remove the configuration class.
Create annotation classes, probably called HomePath and UserPath.
Where class a uses getHomePath() replace that with a String field member named homePath.
Where class b uses getUserPath() replace that with a String field member named userPath.
Modify the class a and b constructors to be #Inject annotated (should already be) and take in a String parameter, respectively annotated with #HomePath and #UserPath and assign the String field member that injected value.
Create bindings in your module's configure method use .annotatedWith() which define correct values; if they're only available at run time, bind a provider.
E.G.
class a {
private String homePath;
#Inject
public a(#HomePath String homePath) {
this.homePath = homePath;
}
public String tellMeAboutHome() {
return "We live in a nice home called " + homePath;
}
}
class customModule extends AbstractModule {
public static final String userPath = "/home/rafael";
public void configure() {
bind(String.class).annotatedWith(HomePath.class).to("/home/");
bind(String.class).annotatedWith(UserPath.class).to(userPath);
}
}
If creating annotations is too much work for you, use the #Named annotation Guice ships with.
There's no single answer to your question, there are only options to choose from, based on your specific situation.
If you know your Configuration class is going to grow AND if it's likely for your A and B classes will use more from it, then pass the whole Configuration object to their constructors. NB: I know this is against the YAGNI principle but sometimes you may know you're gonna need it ;-)
Otherwise, you can consider using #Named injection of your paths so that you reduce A and B classes dependencies to their minimum, which is a good design practice.
The general rule is code to make the dependency graph (which classes know about or depend on other classes/ interfaces) as simple, regular and fixed as possible.
If not passing the Configuration class makes a or b have zero dependencies on on user-written classes, or is necessary to avoid a dependency loop, then use the individual path strings. Otherwise, if it makes more sense to say 'this class has access to configuration info, in a way that may change in the future', pass the class.
I'd avoid the singleton approach, especially if you already have Guice set up.

Categories

Resources