In Roo 2.0 I want to use JPA Query Method - java

I plan on writing a query method like
/**
* TODO Auto-generated method documentation
*
* #param entity
* #return EventExecute
*/
#Transactional
#Autowired
public EventExecute save(EventExecute entity) {
String eventKey = entity.getEventKey();
StepDefinitionRepository sdRepository;
List<StepDefinition> stepDefinitions = sdRepository.findByEventKeyAllIgnoreCaseOrderBySequenceAsc(eventKey);
return getEventExecuteRepository().save(entity);
}
I want to lookup the StepDefintions that match an event key.
I tried following the example in the JPA Documentation...
public class SomeClient {
#Autowired
private PersonRepository repository;
public void doSomething() {
List<Person> persons = repository.findByLastname("Matthews");
}
}
But my sdRepository complains that is it not initialized. I found the getStepDefintionRepository() in the ..ServiceImpl.aj but can't call it.
Is there an example out there?

Ok I figured out my error...here is what works.
#Autowired
private StepDefinitionRepository sdRepository;
/**
* Overridden save method to intercept and process the dynamic steps before saving
*
* #param entity
* #return EventExecute
*/
#Transactional
public EventExecute save(EventExecute entity) {
boolean keepGoing = true;
String eventKey = entity.getEventKey();
Set<NameValuePair> messageVariables = null;
String eventArguments = entity.getEventArguments();
List<NameValuePair> eventVariables = null;
if (!eventArguments.isEmpty()){
eventVariables = _ExtractEventVariables(eventArguments);
}
List<StepDefinition> stepDefinitions = sdRepository.findByEventKeyAllIgnoreCaseOrderBySequenceAsc(eventKey);
for (Iterator<StepDefinition> iterator = stepDefinitions.iterator(); iterator.hasNext();) {

Related

How to pass aws dynamodb table name dynamically using #DynamoDbTable annotation

I have created a java service to get the details from dynamodb it is working fine but my challenge is i hardcoded the table name to the class file #DynamoDbTable annotation in order to work with different environments i feel it is not the right way. I have given my code below could someone help me to resolve the issue.
Code sample
public class DynamodbService {
private DynamoDB client;
private DynamoDBMapper objectMapper;
/**
*
* #param client
* #param objectMapper
*/
#Autowired
public DynamodbService(DynamoDB client, DynamoDBMapper objectMapper) {
this.client = client;
this.objectMapper = objectMapper;
}
public List<Dynamodb> findAll() throws Exception {
DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig.Builder()
.withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(""))
.build();
DynamoDBMapper mapper = new DynamoDBMapper(client, mapperConfig);
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
List<Dynamodb> scanResult = objectMapper.scan(Dynamodb.class, scanExpression);
return scanResult;
}
}
My DynamoDB config
#Configuration
public class DynamoDBconfig {
/**
*
*/
#Value("${amazon.dynamodb.accesskey}")
private String awsAccessKey;
/**
*
*/
#Value("${amazon.dynamodb.secretkey}")
private String awsSecretKey;
#Bean
public AWSCredentials amazonAWSCredentials() {
return new BasicAWSCredentials(aes.getDecryptedvalue(awsAccessKey), aes.getDecryptedvalue(awsSecretKey));
}
/**
*
* #return
*/
#Bean
public DynamoDBMapperConfig dynamoDBMapperConfig() {
return DynamoDBMapperConfig.DEFAULT;
}
/**
*
* #param amazonDynamoDB
* #param config
* #return
*/
#Bean
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig config) {
return new DynamoDBMapper(amazonDynamoDB, config);
}
/**
*
* #return
*/
#Bean
public AmazonDynamoDB amazonDynamoDB() {
return AmazonDynamoDBClientBuilder.standard().withCredentials(amazonAWSCredentialsProvider())
.withRegion(Regions.US_EAST_2).build();
}
/**
*
* #return
*/
#Bean
public DynamoDB dynamoDB() {
return new DynamoDB(amazonDynamoDB());
}
/**
*
* #return
*/
public AWSCredentialsProvider amazonAWSCredentialsProvider() {
return new AWSStaticCredentialsProvider(amazonAWSCredentials());
}
}
ERROR in my dynamodb service
The constructor DynamoDBMapper(DynamoDB, DynamoDBMapperConfig) is undefined
I am unable find out what is the issue. If i use table name in class file it's working fine if i try to replace the table name using code it ends up with error.
DynamoDBMapper expects any implementation of AmazonDynamoDB but not DynamoDB class.
public DynamoDBMapper(
final AmazonDynamoDB dynamoDB,
final DynamoDBMapperConfig config) {
You need to inject only the DynamoDBMapper in your service.
#Bean
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
DynamoDBMapperConfig config = new DynamoDBMapperConfig.Builder().withTableNameOverride(TableNameOverride.withTableNameReplacement(tableName))
.build();
return new DynamoDBMapper(amazonDynamoDB, config);
}
Other option could be using com.amazonaws.services.dynamodbv2.document.DynamoDB class but there you could not use DynamoDBScanExpression and you need to rewrite your code.
String desiredTabledName = "table-name";
Table table = dynamoDB.getTable(desiredTabledName);
You have multiple options.
- table.scan() and table query.
- Index index = table.getIndex(indexName);
index.scan() or index.query()
- You could pass `QuerySpec` and `ScanSpec` to all above.

Abstract class for builder pattern

I have existing model classes that always use builder pattern like this:
public class Model {
public static class Builder {
private boolean isValid;
private List<String> errorMessagesOrNull;
public Builder setIsValid(final boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder setErrorMessages(final List<String> errorMessages) {
this.errorMessagesOrNull = errorMessages;
return this;
}
public List<String> getErrorMessages() {
return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
}
public Model Build() {
return new Model(this);
}
}
private boolean isValid;
private List<String> errorMessages;
private Model(final Builder builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
public boolean getIsValid() {
return isValid;
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
As you see, the model classes always have isValid and errorMessages. I want to write an abstract class to minimize the repeated logic for those model classes.
So I came up like this abstract class:
public abstract class AbstractModel<T extends AbstractModel<T>> {
public static abstract class Builder<T> {
private boolean isValid;
private List<String> errorMessagesOrNull;
public Builder<T> setIsValid(final boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder<T> setErrorMessages(final List<String> errorMessages) {
this.errorMessagesOrNull = errorMessages;
return this;
}
public List<String> getErrorMessages() {
return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
}
public abstract T Build();
}
private boolean isValid;
private List<String> errorMessages;
private AbstractModel(final Builder<T> builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
public boolean getIsValid() {
return isValid;
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
But it's not really working as I intended. When I extends the abstract class:
public class Model extends AbstractModel<Model> {
// Empty here since all fields are extended
}
I cannot do something like:
Model model = new Model.Builder.setIsValid(true).Build();
I want the abstract class has Builder static class, so that I don't need to write the static class Builder every time.
Please advise.
You also need to implement the Builder.
public class Model extends AbstractModel<Model>{
private Model(final Builder builder) {
super(builder);
}
public static class Builder2 extends AbstractModel.Builder<Model> {
#Override
public Model Build() {
return new Model(this);
}
}
}
then it possible to call
Model model = new Model.Builder2().Build();
EDIT
Also, the constructor of AbstractBuilder also must be protected.
protected AbstractModel(final Builder<? extends Builder<T>> builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
I think that there is a huge flaw in your logic. The program itself doesn't really make any sense at all. Why do you construct a Model with the Builder class in the first place? I think it is better to show you how you should have written your program, instead of just "bodging" it together. Alright, let us start with the Model class.
Let's say the Model class cannot be constructed without a Builder. Would it then make sense to add the Builder class into the Model class? Short answer: no, it wouldn't. Instead, the Builder class should contain the Model class as a non-static internal class.
/**
* The {#code Builder} can construct new instances of the {#code Model} class.
*
* #see Model
*/
public class Builder
{
private final String[] log;
/**
* The {#code Model} class can do something. You can only construct it through a {#code Builder}.
*
* #see Builder
*/
public class Model
{
private final Builder builder;
/**
* Constructs a new {#code Model} with the specified argument.
*
* #param builder the {#code Builder} that constructed the model.
*/
public Model(final Builder builder)
{
this.builder = builder;
}
/**
* Returns the associated {#code Builder}.
*
* #return the builder that constructed the model.
*/
public Builder getBuilder()
{
return this.builder;
}
}
/**
* Constructs a new instance of the {#code Builder} class with the specified argument.
*
* #param log the log of the {#code Builder}.
*/
public Builder(final String... log)
{
this.log = log;
}
/**
* Tries to {#code build} a new instance of the {#code Model} class.
*
* #return the constructed {#code Model}.
*/
public Model build()
{
return new Model(this);
}
/**
* Returns the log of the {#code Builder}.
*
* #return an log.
*/
public String[] getLog()
{
return this.log;
}
/**
* Determines whether or not the {#code Builder} is valid.
*
* #return {#code true} when the specified {#code log} is not {#code null}; {#code false} otherwise.
*/
public boolean isValid()
{
return this.log != null;
}
}
No class other than the Builder can construct a Model. However, if you construct a new instance of the Builder class and get the result of invoking the build method, you'll have access to all public variables and methods.
If you know want to construct a Model, you can do that just like that:
Builder.Model model = new Builder().build();
If you don't want the Builder. prefix, just add an import statement that imports the Model class.
import organisation.projectname.pathToBuilder.Builder.Model;

How to detach logic from controllers and put it to some handler using annotations?

In our project we already have some necessary controllers and my task is to make it easier. It should work like this: I just put an annotation under a controller and a handler do all its job. What I already have:
/**
* This annotation marks collector methods
*/
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Collect {
}
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface Collectors {
/**
* An array of subclasses that can load and provide values for
* generating a ModelMap.
*/
Class<?>[] value();
}
I can't find any example how to do it. Controller example:
#Controller
public class TestController {
private final SchoolService schoolService;
private final TeacherService teacherService;
public TestController(SchoolService schoolService, TeacherService teacherService) {
this.schoolService = schoolService;
this.teacherService = teacherService;
}
/**
* Saves the static list of users in model and renders it
* via freemarker template.
*
* #param model
* #return The index view (FTL)
*/
#Collectors(SchoolCollector.class)
#RequestMapping(value = "freemarker/freemarkertest", method = RequestMethod.GET)
public String index(#ModelAttribute("model") ModelMap model) {
List<SchoolDTO> schoolList = new ArrayList<SchoolDTO>();
schoolList = schoolService.findAll();
model.addAttribute("schoolList", schoolList);
return "freemarkertest";
}
/**
* Add a new School
*
* #param schoolDTO
* #return Redirect back to same /freemarkertest page to display school list, if successful
*/
#Collectors(SchoolCollector.class)
#RequestMapping(value = "freemarker/freemarkertest/add", method = RequestMethod.POST)
public String add(#ModelAttribute("schoolDTO") SchoolDTO schoolDTO) {
if(schoolDTO.getName() != null && !schoolDTO.getName().isEmpty() &&
schoolDTO.getEnabled() != null) {
schoolService.save(schoolDTO);
return "redirect:";
} else {
return "redirect:error"; //TODO: create error page
}
}
/**
* Get list of teachers.
*
* #param model
* #param schoolId
* #return The index view (FTL)
*/
#Collectors(SchoolCollector.class)
#RequestMapping(value = "freemarker/teachers/{schoolId}", method = RequestMethod.GET)
public String index(#ModelAttribute("model") ModelMap model, #PathVariable Long schoolId) {
List<TeacherDTO> teachers = teacherService.getAllBySchoolId(schoolId);
model.addAttribute("teachersList", teachers);
model.addAttribute("schoolId", schoolId);
return "teachers";
}
}
What you need are HandlerInterceptorAdapters. Those have to be defined in your SpringMvc-servlet.xml, than those will intercept all your requests.
public class CollectorHandler extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if (handler instanceof HandlerMethod && modelAndView != null) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
if (handlerMethod.getMethodAnnotation(Collectors.class) == null) {
return;
}
/**
* Your logic here
*/
}
}
}
For further reading:
http://www.baeldung.com/spring-mvc-handlerinterceptor
https://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/
PS: I also want to add, that your code will not work, as you have some "errors" in it... returning Strings instead of objects as an example

XML to Object Unmarshalling using JAXB

I need to Unmarshal XML to Java Object, I have tried with below code. Its create an Object but set all value as a null. code for same:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Dispatch implements java.io.Serializable {
private Integer dispatchId;
private Order order;
/**
* #return the dispatchId
*/
public Integer getDispatchId() {
return dispatchId;
}
/**
* #param dispatchId
* the dispatchId to set
*/
public void setDispatchId(Integer dispatchId) {
this.dispatchId = dispatchId;
}
/**
* #return the order
*/
public Order getOrder() {
return order;
}
/**
* #param order
* the order to set
*/
public void setOrder(Order order) {
this.order = order;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return ""+this.dispatchId;
}
}
I have Dispatch Class with other sub class, i need to convert XML to Java Object. Code for same:
Public class UnmarshalExample {
public static void main(String[] args) {
String xmlString = "<ns1:dispatch xmlns:ns1=\"http://service.order.com\"><ns1:dispatchId>1</ns1:dispatchId><ns1:order><ns1:totalAmount>1000.0</ns1:totalAmount></ns1:order></ns1:dispatch>";
Dispatch dispatch = (Dispatch) JAXB.unmarshal(
new StringReader(xmlString), Dispatch.class);
System.out.println(dispatch);
}
}
As a output it will return null.
Can any one tell me whats wrong thing in my code?
That is odd, I pasted you code and ran and it produces dispatchId 1:
Dispatch class:
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Dispatch implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Integer dispatchId;
/**
* #return the dispatchId
*/
public Integer getDispatchId() {
return dispatchId;
}
/**
* #param dispatchId
* the dispatchId to set
*/
public void setDispatchId(Integer dispatchId) {
this.dispatchId = dispatchId;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return ""+this.dispatchId;
}
}
Test class
import java.io.*;
import javax.xml.bind.JAXB;
public class Test {
public static void main(String[] args) {
String xmlString = "<ns1:dispatch xmlns:ns1=\"http://service.order.com\"><ns1:dispatchId>1</ns1:dispatchId><ns1:order><ns1:totalAmount>1000.0</ns1:totalAmount></ns1:order></ns1:dispatch>";
Dispatch dispatch = (Dispatch) JAXB.unmarshal(
new StringReader(xmlString), Dispatch.class);
System.out.println(dispatch);
}
}
output is
1
The order is of the type Order. We don't see any code of this class.
This is probably the cause of it as well. You may not provide decent data for the Order to be constructed.
To see how namespaces are used: http://blog.bdoughan.com/2012/11/applying-namespace-during-jaxb-unmarshal.html

Spring HATEOAS Resource Assembler and Resource Links with many variables

I'm working on REST API with Spring HATEOAS and the Spring stack, and i have some problems with links into resources.
Here is my code :
the Controller :
#RestController
#RequestMapping("/apporteurs/{idInt}/ribs")
public class RibController {
#Autowired
private RibResourceAssembler ribResourceAssembler;
#Autowired
private RibRepository ribRepository;
/**
* Methode GET permettant d'obtenir un Rib par son ID
*
* #param idRib ID du Rib
* #return RibResource
*/
#RequestMapping(value = "/{idRib}", method = RequestMethod.GET)
#ResponseBody
public RibResource getRibById(#PathVariable Long idInt, #PathVariable Long idRib) {
CurrentUserUtils.checkAuthorizationByApporteur(idInt);
return ribResourceAssembler.toResource(ribRepository.getRibById(idRib));
}
}
The Assembler :
#Component
public class RibResourceAssembler extends ResourceAssemblerSupport<Rib, RibResource> {
public static final long TMP_IDS = 1234L;
#Autowired
private RibResourceMapper ribResourceMapper;
public RibResourceAssembler() {
super(RibController.class, RibResource.class);
}
#Override
public RibResource toResource(Rib rib) {
return createResourceWithId(rib.getId(), rib);
}
/**
* TODO : mettre le lien vers l'editique Mandat
*
* #param rib Rib à instancier en Resource.
* #return RibResource
*/
#Override
protected RibResource instantiateResource(Rib rib) {
RibResource ribResource = ribResourceMapper.fromRib(rib, rib.getLastMandat());
ribResource.removeLinks();
CustomUserDetails user = CurrentUserUtils.getCurrentUser();
UriComponentsBuilder uriBuilderMandat = linkTo(RibController.class).toUriComponentsBuilder();
String uri = uriBuilderMandat.path("/{idRib}/mandats/{idMandat}").buildAndExpand(user.getIdInt(), rib.getId(), TMP_IDS).toUriString();
Link linkEditiqueMandat = new Link(uri).withRel("editiqueMandat");
UriComponentsBuilder uriBuilderRib = linkTo(RibController.class).toUriComponentsBuilder();
String uriSelf = uriBuilderRib.path("/{idRib}").buildAndExpand(user.getIdInt(), rib.getId()).toUriString();
Link linkUriSelf = new Link(uriSelf).withSelfRel();
ribResource.add(linkEditiqueMandat);
ribResource.add(linkUriSelf);
return ribResource;
}
}
The Resource :
public class RibResource extends ResourceSupport {
private Long idRib;
private String rum;
private String iban;
private String libelle;
private String dateFin;
private String dateCreation;
private String dateModification;
private String codeOperateurCreation;
private String dateRegulationMandat;
private boolean actif;
private boolean reactivable;
private CodeValueResource modeReglement;
/*Gzetter & setters, etc*/
}
As you can see, my controller have some parameters in the URI : idInt and idRib.
So for make a SelfLink, i have to know this parameters for make something like "/apporteurs/1234/ribs/1234", but i think the Assembler want only one parameter, and a "simple" URI.
I have this stack trace :
2014-11-25 12:02:09.365 ERROR 20860 --- [nio-9080-exec-1] w.s.m.m.a.ResponseEntityExceptionHandler : Not enough variable values available to expand 'idInt'
So i'm looking for an elegant solution to do this, because i didn't find anything ^^
I saw something with ResourceProcessor, but i'm not using Spring Data Rest.
Can you help me ? Thank you in advance ;)
EDIT :
The result should be :
_links": {
"editiqueMandat": {
"href": "http://localhost:9080/apporteurs/6797/mandats/5822"
},
"self": {
"href": "http://localhost:9080/apporteurs/6797/ribs/1234"
}
}
#Override
public RibResource toResource(Rib rib) {
return createResourceWithId(rib.getId(), rib);
}
createResourceWithId() internally creates a self link based on the controller's URL. In your case that contains the placeholder {idInt} so you would have to provide a parameter for that:
CustomUserDetails user = CurrentUserUtils.getCurrentUser();
return createResourceWithId(rib.getId(), rib, user.getIdInt());
The better choice would be not to call createResourceWithId() at all. Just move everything you now have in instantiateResource() to toResource().

Categories