java annotation processing: problems generating a new class - java

I'm playing with java annotation processing to learn how to generate java code on compile time. I've created an abstract processor that (using javapoet) creates a new class. However I can't manage to make it work.
I've compressed the example in a single java class.
What I'm doing wrong?
When I compile the project I get:
Error:java: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider com.mateuyabar.AnnotProc not found
Here is the java code:
package com.mateuyabar;
import com.google.auto.service.AutoService;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
#AutoService(Processor.class)
public class AnnotProc extends AbstractProcessor{
public #interface MyAnnotation {}
#MyAnnotation
public static void dummyForAnnotation(){}
#Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
for(Element el:env.getElementsAnnotatedWith(MyAnnotation.class)){
System.out.println(el.asType());
}
MethodSpec sampleMethod = MethodSpec.methodBuilder("sampleMethod").addModifiers(Modifier.PUBLIC).returns(String.class).addParameter(String.class, "param1")
.addStatement("return $S+$N", "Welcome, ", "name").build();
TypeSpec customerService = TypeSpec.classBuilder("MyGeneratedClass").addModifiers(Modifier.PUBLIC).addMethod(sampleMethod).build();
JavaFile javaFile = JavaFile.builder("com.mateuyabar", customerService).build();
try {
javaFile.writeTo(System.out);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
#Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(MyAnnotation.class.getName());
}
#Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
public static void main(String[] args){
System.out.println(new com.mateuyabar.MyGeneratedClass().sampleMethod("a"));
}
}

Related

Error: While resolving module, the Haste package was found. the module could not be found within the package

I am trying the new arch of react native. I have enabled it in my gradle.properties file. This error is for android only and I have not tried iOS yet.
I am following the exact sample of Calculator mentioned over here.
I get an error saying
error: Error: While resolving module `rtn-calculator/js/NativeCalculator.js`, the Haste package `rtn-calculator` was found. However the module `js/NativeCalculator.js` could not be found within the package. Indeed, none of these files exist:
* `/Users/transformhub/Desktop/rnapp/RTNCalculator/js/NativeCalculator.js(.native|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)`
* `/Users/transformhub/Desktop/rnapp/RTNCalculator/js/NativeCalculator.js/index(.native|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)`
at resolveHasteName (/Users/transformhub/Desktop/rnapp/node_modules/metro-resolver/src/resolve.js:173:9)
at Object.resolve (/Users/transformhub/Desktop/rnapp/node_modules/metro-resolver/src/resolve.js:63:20)
at ModuleResolver.resolveDependency (/Users/transformhub/Desktop/rnapp/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:111:31)
at DependencyGraph.resolveDependency (/Users/transformhub/Desktop/rnapp/node_modules/metro/src/node-haste/DependencyGraph.js:260:43)
at Object.resolve (/Users/transformhub/Desktop/rnapp/node_modules/metro/src/lib/transformHelpers.js:177:21)
at Graph._resolveDependencies (/Users/transformhub/Desktop/rnapp/node_modules/metro/src/DeltaBundler/Graph.js:432:35)
at Graph._processModule (/Users/transformhub/Desktop/rnapp/node_modules/metro/src/DeltaBundler/Graph.js:218:38)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Graph._addDependency (/Users/transformhub/Desktop/rnapp/node_modules/metro/src/DeltaBundler/Graph.js:314:20)
at async Promise.all (index 2)
The complete repo is here
Below is sample code
NativeCalculator.ts
import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
import {TurboModuleRegistry} from 'react-native';
export interface Spec extends TurboModule {
add(a: number, b: number): Promise<number>;
}
export default TurboModuleRegistry.get<Spec>('RTNCalculator') as Spec | null;
package com.rtncalculator;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.module.model.ReactModuleInfo;
import com.facebook.react.module.model.ReactModuleInfoProvider;
import com.facebook.react.TurboReactPackage;
import java.util.Collections;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
public class CalculatorPackage extends TurboReactPackage {
#Nullable
#Override
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
if (name.equals(CalculatorModule.NAME)) {
return new CalculatorModule(reactContext);
} else {
return null;
}
}
#Override
public ReactModuleInfoProvider getReactModuleInfoProvider() {
return () -> {
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
moduleInfos.put(
CalculatorModule.NAME,
new ReactModuleInfo(
CalculatorModule.NAME,
CalculatorModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
true, // hasConstants
false, // isCxxModule
true // isTurboModule
));
return moduleInfos;
};
}
}
package com.rtncalculator;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.Map;
import java.util.HashMap;
import com.rtncalculator.NativeCalculatorSpec;
public class CalculatorModule extends NativeCalculatorSpec {
public static String NAME = "RTNCalculator";
CalculatorModule(ReactApplicationContext context) {
super(context);
}
#Override
#NonNull
public String getName() {
return NAME;
}
#Override
public void add(double a, double b, Promise promise) {
promise.resolve(a + b);
}
}
This is a react native issue introduced in 0.70 and was resolved in 0.71. Check here for more details

How can i use exceptions in springboot

i am new in spring boot, i following the tuorial from Pluralsight.
i got problem by using exceptions
here is my service interface
package com.stev.pillecons.pilleCons.services;
import com.stev.pillecons.pilleCons.models.LePille;
import java.util.List;
public interface PilleService {
List<LePille> listPilles();
LePille findPille(Integer id);
}
here is how i implements the services
package com.stev.pillecons.pilleCons.services;
import com.stev.pillecons.pilleCons.exceptions.PilleException;
import com.stev.pillecons.pilleCons.models.LePille;
import com.stev.pillecons.pilleCons.repositories.LePilleRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
#Service
public class PilleServiceImpl implements PilleService{
#Autowired
private LePilleRepo pilleRepo;
#Override
public List<LePille> listPilles() {
return (List<LePille>) pilleRepo.findAll();
}
#Override
public LePille findPille(Integer id) {
Optional<LePille> optionalLePille = pilleRepo.findById(id);
if (optionalLePille.isPresent())
return optionalLePille.get();
else
return new PilleException("pille not found");
}
}
i got red under line to this line : return new PilleException("pille not found");
here is my exception
package com.stev.pillecons.pilleCons.exceptions;
public class PilleException extends RuntimeException {
public PilleException (String ex) {super(ex);}
}
EDIT
i use this code
#Override
public LePille findPille(Integer id) {
return pilleRepo.findById(id).orElseThrow(()-> new PilleException("pille not found"));
}
it works, why my code doesn't work ?
An exception is not returned it is thrown.
throw new PilleException("pille not found");

Spring Data Cassandra cant find entity class

I'm trying to persist a cassandra entity but on startup I get:
Caused by: org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type class com.service.model.Cart!
This is my entity class:
package com.service.model;
import io.vavr.collection.LinkedHashMap;
import io.vavr.collection.Map;
import lombok.Getter;
import lombok.ToString;
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
import org.springframework.data.cassandra.core.mapping.Table;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
#ToString
#Table("carts")
public class Cart {
#Getter
#PrimaryKey
private final UUID uuid;
private final Map<CartItemKey, CartItem> items;
public Cart(UUID uuid) {
this(uuid, LinkedHashMap.empty());
}
private Cart(UUID uuid, Map<CartItemKey, CartItem> items) {
this.uuid = Objects.requireNonNull(uuid, "Cart's uuid cannot be null");
this.items = Objects.requireNonNull(items, "Cart's items cannot be null");
}
}
This is my CassandraConfig:
package com.service.configuration;
import com.service.model.Cart;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.cassandra.config.AbstractClusterConfiguration;
import org.springframework.data.cassandra.core.convert.CassandraCustomConversions;
import org.springframework.data.cassandra.core.cql.keyspace.CreateKeyspaceSpecification;
import org.springframework.data.cassandra.core.cql.keyspace.KeyspaceOption;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.singletonList;
#Configuration
public class CassandraConfig extends AbstractClusterConfiguration {
#Value("${spring.data.cassandra.keyspace-name}")
private String keyspaceName;
#Value("${spring.data.cassandra.contact-points}")
private String contactPoints;
#Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
return singletonList(
CreateKeyspaceSpecification.createKeyspace(keyspaceName)
.ifNotExists()
.with(KeyspaceOption.DURABLE_WRITES, true)
.withSimpleReplication());
}
#Override
protected boolean getMetricsEnabled() {
return false;
}
#Override
protected String getContactPoints() {
return contactPoints;
}
#Bean
public CassandraCustomConversions customConversions() {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new CartWriteConverter());
converters.add(new CartReadConverter());
return new CassandraCustomConversions(converters);
}
static class CartWriteConverter implements Converter<Cart, String> {
public String convert(Cart source) {
try {
return new ObjectMapper().writeValueAsString(source);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
static class CartReadConverter implements Converter<String, Cart> {
public Cart convert(String source) {
if (StringUtils.hasText(source)) {
try {
return new ObjectMapper().readValue(source, Cart.class);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
return null;
}
}
}
And lastly my Application:
package com.service.cart;
import org.axonframework.springboot.autoconfig.AxonServerAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
#EnableCaching
#EnableAsync
#EnableFeignClients
#SpringBootApplication
#EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
AxonServerAutoConfiguration.class})
#EnableCassandraRepositories(basePackages = "com.service.repository")
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
What seems puzzling to me is that when I remove customConversions() bean it fails with a different error - not being able to map vavr Map, so spring must have scanned and registered this entity so that it got inspected. This is expected while it is not cassandra data type but in my understanding adding my custom conversions should solve this problem.
I also tried experimenting with #EntityScan with the same results.
Any help would be appreciated.

impossible to import android.content.res.Resources

I can't find how to import android.content.res.Resources;
Here is my code:
package com.mycompany.fortune;
import com.google.gson.JsonObject;
import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;
import android.content.res.Resources; //This don't work
import retrofit.http.GET;
import java.util.List;
import java.util.Random;
public class FortuneClient {
private static final String API_URL = "http://www.myurl.fr";
private interface FortuneService {
#GET("/test.php")
void getFortune(Callback<JsonObject> callback);
}
public static class OnFortuneListener {
public void onFortune(String fortune) {
}
}
private static Random rng = new Random();
private FortuneService service;
public FortuneClient() {
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(API_URL)
.build();
service = adapter.create(FortuneService.class);
}
public void getFortune(final OnFortuneListener listener) {
service.getFortune(new Callback<JsonObject>() {
#Override
public void success(JsonObject json, Response response) {
String test = json.getAsJsonObject("0").getAsJsonObject("title").toString();
String test2 = json.getAsJsonObject("0").getString('title');
listener.onFortune(test2);
}
#Override
public void failure(RetrofitError error) {
listener.onFortune(error.toString());
}
});
}
}
the error is: "Error:(8, 26) Gradle: error: package android.content.res does not exist"
What I tried:
-Make, remake, build, clean, rebuild,
-Invalidate cache and restart,
-Verify the java/sdk/jdk positions,
-Stupid things on the gradle/xml files.
This import android.content.res.Resources; //This don't work is used in your application code to access the resources. To Access any particular resource you should pass the context to this class atleast .

Spring-Data-Rest Validator

I have been trying to add spring validators to a spring-data-rest project.
I followed along and setup the "getting started" application via this link: http://spring.io/guides/gs/accessing-data-rest/
...and now I am trying to add a custom PeopleValidator by following the documents here:
http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/validation-chapter.html
My custom PeopleValidator looks like
package hello;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class PeopleValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return true;
}
#Override
public void validate(Object target, Errors errors) {
errors.reject("DIE");
}
}
...and my Application.java class now looks like this
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public PeopleValidator beforeCreatePeopleValidator() {
return new PeopleValidator();
}
}
I would expect that POSTing to the http://localhost:8080/people URL would result in an error of some kind since the PeopleValidator is rejecting everything. However, no error is thrown, and the validator is never called.
I have also tried manually setting up the validator as shown in section 5.1 of the spring-data-rest documentation.
What am I missing?
So it appears that the before/after "save" events only fire on PUT and PATCH. When POSTing, the before/after "create" events fire.
I tried it the manual way again using the configureValidatingRepositoryEventListener override and it worked. I'm not sure what I'm doing differently at work than here at home. I'll have to look tomorrow.
I sure would love to hear if others have suggestions on why it wouldn't work.
For the record, here is what the new Application.java class looks like.
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application extends RepositoryRestMvcConfiguration {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", new PeopleValidator());
}
}
Looks like the feature is currently not implemented (2.3.0), unluckily there are no constants for the event names otherwise the solution below would not be that fragile.
The Configuration adds all properly named Validator beans to ValidatingRepositoryEventListener using the right event.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.validation.Validator;
#Configuration
public class ValidatorRegistrar implements InitializingBean {
private static final List<String> EVENTS;
static {
List<String> events = new ArrayList<String>();
events.add("beforeCreate");
events.add("afterCreate");
events.add("beforeSave");
events.add("afterSave");
events.add("beforeLinkSave");
events.add("afterLinkSave");
events.add("beforeDelete");
events.add("afterDelete");
EVENTS = Collections.unmodifiableList(events);
}
#Autowired
ListableBeanFactory beanFactory;
#Autowired
ValidatingRepositoryEventListener validatingRepositoryEventListener;
#Override
public void afterPropertiesSet() throws Exception {
Map<String, Validator> validators = beanFactory.getBeansOfType(Validator.class);
for (Map.Entry<String, Validator> entry : validators.entrySet()) {
EVENTS.stream().filter(p -> entry.getKey().startsWith(p)).findFirst()
.ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue()));
}
}
}
A bit of a stab in the dark - I've not used spring-data-rest. However, after having a read of the tutorial you're following, I think the problem is that you need a PersonValidator not a PeopleValidator. Rename everything accordingly:
PersonValidator
package hello;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
public class PersonValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return true;
}
#Override
public void validate(Object target, Errors errors) {
errors.reject("DIE");
}
}
Application
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
#Configuration
#EnableJpaRepositories
#Import(RepositoryRestMvcConfiguration.class)
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public PersonValidator beforeCreatePersonValidator() {
return new PersonValidator();
}
}
Another way of doing it is to use annotated handlers as specified here
http://docs.spring.io/spring-data/rest/docs/2.1.0.RELEASE/reference/html/events-chapter.html#d5e443
Here is an example of how to use annotated handlers:
import gr.bytecode.restapp.model.Agent;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.HandleBeforeSave;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import org.springframework.stereotype.Component;
#Component
#RepositoryEventHandler(Agent.class)
public class AgentEventHandler {
public static final String NEW_NAME = "**modified**";
#HandleBeforeCreate
public void handleBeforeCreates(Agent agent) {
agent.setName(NEW_NAME);
}
#HandleBeforeSave
public void handleBeforeSave(Agent agent) {
agent.setName(NEW_NAME + "..update");
}
}
Example is from github edited for brevity.

Categories

Resources