If I create a custom annotation like this:
public #interface TODO
{
String msg();
String start_date();
}
then a method:
#TODO
(
msg="will be developed!",
start_date="05/01/2010"
)
public static void Calculator()
{
}
after I call it:
Calculator();
If I wanted that the compiler warn me about it how could I do that?
There was a similar question, some weeks ago. Here is the link to both the question and my answer.
You can easily adapt this code to your needs.
You must write an annotation processor and invoke apt to run it on your code.
Use the Annotation Processing Tool (apt) to make your own AnnotationProcessor and print the message with javax.annotation.processing.Messager
If you are using an IDE, there are plenty of good options. For Eclipse:
use the built-in plug-in which locates all TODO, FIXME, etc. words in your code and puts them in a special view.
register your own custom builder which can show you the warnings
Related
I have a Kotlin Gradle project. I added Lombok as a dependency and also registered it with kapt
compileOnly("org.projectlombok:lombok:$lombokVersion")
kapt("org.projectlombok:lombok:$lombokVersion")
I would like to use the #Slf4j annotation for automatic logger generation. It works for Java classes but not for the Kotlin ones.
Is using Kotlin and Lombok together even possible as of now? If I annotate a Kotlin class with #Slf4j and use log inside it I get
Unresolved reference: log
Evidently no annotation processing is applied.
Lombok does not run on your source code, but on the AST. Anyway, it is an annotation processor that is run at compile-time by the Java compiler. The Kotlin compiler does not use these annotation processors. See also the answer https://stackoverflow.com/a/35530223/2621917 straight from the horse’s mouth.
You cannot use annotation #Slf4j, but manually create its object in the class required.
Refer https://www.reddit.com/r/Kotlin/comments/8gbiul/slf4j_loggers_in_3_ways/
If all you want to use Lombok for is #Slf4j, then I'd suggest using kotlin-logging instead: https://github.com/MicroUtils/kotlin-logging
It's a simple wrapper around slf4j, so instead of annotating your class with #Slf4j, you use:
// Place definition above class declaration to make field static
private val logger = KotlinLogging.logger {}
// ...
logger.debug { "A message only logged if debug is enabled. With $variable support." }
Lombok's builder annotation support has been added to kotlin 1.8 as of late December 2022.
You can learn how to configure the plugin here.
In Short, add
plugins {
id 'org.jetbrains.kotlin.plugin.lombok' version '1.8.0'
id 'io.freefair.lombok' version '5.3.0'
}
to your Groovy/Gradle files, and/or take a look at the sample project.
It's not supported and, by the looks of things, it isn't going to be.
from kotlin 1.7.20 with K2 compiler it is possible.
https://kotlinlang.org/docs/whatsnew1720.html#support-for-kotlin-k2-compiler-plugins
For logging the best I could do - because #Slf4j did not work - was like creating abstract log class like:
package org.example
import org.slf4j.LoggerFactory
import org.slf4j.Logger
abstract class Log {
val log: Logger = LoggerFactory.getLogger(this.javaClass)
}
and usage:
package org.example
class MyClass {
companion object : Log() {}
#Test
fun someFun() {
log.info("Logging info")
}
}
I can't see how it would work without additional support from the lombok team.
Lombok is based on annotation processing so it runs during compilation time and runs on your source code, so I guess it assumes Java's syntax.
Trying to find a way to wraps an object, which is auto generated based on some model with lots of getters and setters. For example:
class ObjectToWrap {
public int getIntA();
public int getIntB();
... // Tons of other getters
}
I have to create a wrapper that wraps this object and use some annotation that generates methods from ObjectToWrap for me. Code looks like the following:
class Wrapper {
private ObjectToWrap obj;
public int getIntA() {
return obj.getIntA();
}
public int getIntB() {
return obj.getIntB();
}
... // Tons of other getters
}
Is there an annotation to do this? I just don't want to make the code look lengthy.
Take a look at Project Lombok which has a #Delegate annotation which does exactly what you want.
#Delegate documentation
I think you would be able to do this:
import lombok.Delegate;
class Wrapper {
//the types field in the annotation says
//to only auto generate deleagate methods
//for only the public methods in the ObjectToWrap class
//and not any parent classes if ObjectToWrap extended something
#Delegate(types = ObjectToWrap.class)
private ObjectToWrap obj;
}
If you are using the maven build infrastructure with dependency management, you could have a dependent sub-project that collects the generated sources as-is (not as code). Another sub-project could then generate real sources out of them (source code transformation) as zip, which then could be imported by maven in the main project as pre-compile target.
On that basis you could use dynamic proxy classes, or even immediate generated classes.
The only other alternative would be to use the java scripting API, and do the business in JavaScript or so. Loosing the type safeness of java and lowering the software quality.
Unfortunately the alternative of hybrid usage of another JVM language I cannot consider productive. The very nice and powerful Scala still is too wild/complex/ticklish.
I'm working right now with Apache Wicket using Groovy language. I was wondering is there any chance to improve Apache Wicket for Groovy programming?
What's on my mind. I want have ability to write code like this:
new AjaxLink("ajaxLink", {link, target -> /* some Closure body */ })
But without creating decorators like
class GroovyWicketAjaxLink extends AjaxLink {
def clickClosure;
GroovyWicketAjaxLink(wicketId, onClickClosure) {
super(wicketId)
this.clickClosure = onClickClosure
}
void onClick(AjaxRequestTarget target) {
clickClosure.call([this, target]);
}
}
Maybe there is some way to create some kind of DefaultWicketGroovyMethods with support exactly like for DefaultGroovyMethods?
I think you should start an open-source project called Gricket, a Groovy DSL for Wicket, where you could write stuff like:
code = { // i wrote this in a closure, but you can write it in a separate file
ajaxLink id: "link", onClick: { ->
// write the link
}
}
Which would be parsed as scripts, and missingMethod calls are resolved as instantiation of apache wicket classes:
class GricketParser {
def components = []
def methodMissing(String method, args) {
def clazz = "org.apache.wicket.ajax.markup.html." + method.capitalize() as Class
def component = clazz.newInstance()
args[0].each { key, value -> component[key] = value }
}
}
code.delegate = new GricketParser()
code()
You could also apply metaprogramming on top of String class instead of parsing a script
Update:
Seems like the idea was proposed back in 2008, with some problems regarding groovy support for anonymous classes. Time for a new WicketBuilder? :-)
Finally, I had created the project that you are asking for. I used ExtensionModule groovy feature, so you just need to import a dsl project from github and start using it.
The syntax for AjaxLink with label will look like this:
#Override
void onInitialize() {
ajaxLink('link') {
label('label')
click { AjaxRequestTarget t, AjaxLink link -> // or even without these params
}
}
}
You can chain components like you are imagine them in your mind :) Feel the groovy freedom with Wicket. All methods inside WicketDSL class includes #DelegatesTo and #ClosureParams annotations, so you can feel great IDE support for DSL. Also #CompileStatic groovy annotation is supported for all your code written with this DSL. It should great increase performance.
Checkout two github branches here:
https://github.com/eugene-kamenev/wicket-groovy-DSL
And feel free to contact me.
I have no control of where System.getProperty is called in the project. I want to log some information in the console whenever System.getProperty("SomeProperty"); is called.
How to achieve this.
You could try creating a java.lang.SecurityManager that throws an exception or prints some stuff out in the checkPropertyAccess(String) method. It gets called when something accesses System properties.
More info about Security Managers:
http://docs.oracle.com/javase/tutorial/essential/environment/security.html
http://java.sun.com/developer/onlineTraining/Programming/JDCBook/signed2.html
You would like to use AspectJ and its pointcut. Take a look here for more.
Here is an example adapted from the tutorial mentioned above.
#Aspect
public class Foo {
#Pointcut("call(* java.lang.System.getProperty(..))")
void anyUtilityCall() {
// do whatever you need
}
}
I've got a project that has gwt-log logging lines scattered throughout. Now I'm trying to write some unit tests and nothing seems to be working.
Any class I test that uses the gwt-log facility causes the following exception to be raised:
Caused by: com.googlecode.gwt.test.exceptions.GwtTestConfigurationException:
A custom Generator should be used to instanciate
'com.allen_sauer.gwt.log.client.LogMessageFormatter',
but gwt-test-utils does not support GWT compiler API,
so you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
I have no need for the logger to function during unit tests, I'd prefer to mock it away.
I've attempted to use Mockito to mock the logger, in a few different ways... obviously I have no idea what I'm doing here, none of the following code snippets helped the situation:
public class ClockTest extends GwtTest {
#Mock private LogMessageFormatter lmf;
...
or
...
#Before
public void init() throws Exception {
LogMessageFormatter lmf = mock(LogMessageFormatter.class);
...
Any clues on how to work this out would be most appreciated!
Colin is right, you have 2 ways to deal with your error :
1) Mock the LogMessageFormatter, or at a higher level, mock your Logger instance. gwt-test-utils provides a simple API for mocking with both Mockito or EasyMock : http://code.google.com/p/gwt-test-utils/wiki/MockingClasses
2) provide your own GwtCreateHandler to instanciate the LogMessageFormatter, or at a higher your own Logger instance.
Internally, gwt-log relies on GWT's deferred binding to instanciate a LogMessageFormatter object based on your configuration, which is parsed at compile time. It use GWT's generator API to create the LogMessageFormatter class, but gwt-test-utils is not able to use those kind of Generators.
You'll have to do it "by hand", with gwt-test-utils deferred binding support : GwtCreateHandlers.
Your "LoggerGwtCreateHandler" could use JDK's InvocationHandler and Proxy classes to write a proxy for the Logger interface which would simply silent each method call, since I guess you won't care about any log call in your tests.
Here is a discussion on how to write a GwtCreateHandler : https://groups.google.com/forum/?fromgroups#!topic/gwt-test-utils-users/r_cbPsw9nIE
From the error message you posted:
you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
These are the two options you have to proceed. I've only just begun to work with gwt-test-utils, but the main premise is that it doesn't run the GWT compiler or Dev Mode, so it needs other ways to handle implementing 'magic' features like GWT.create. Its method is to either require you to mock the instance (this should be a fairly common idea in most of your tests for other objects involved in testing) or to provide something like a generator, and hook it up using GwtTest.addGwtCreateHandler.
Building a mock logger shouldn't be too bad, nor should implementing GwtCreateHandler - you just need to make something that has all the log methods. If you want the logging to work, then those methods need to actually invoke some other logger, like java.util.Logger, log4j, slf4j, etc but that is not required for just getting the tests to run (but may be handy for making sure that you logging works, or finding out why your test is failing.
for those still in pain with this damn problem here is what I managed to get (With a lot of pain too ...). It'll solve the conflict between Gwt-test-utils and Gwt-log.
You're of course welcome to modify the format method ;) :
#Before
public void correctLog() {
this.addGwtCreateHandler(new GwtCreateHandler() {
#Override
public Object create(Class<?> classLiteral) throws Exception {
if (classLiteral.isAssignableFrom(LogMessageFormatter.class)) {
return new LogMessageFormatter() {
#Override
public String format(String logLevelText, String category,
String message, Throwable throwable) {
return message + " : " + throwable.getLocalizedMessage();
}
};
}
return null;
}
});
}