When calling the generated api when using a paginator, is there any way i can call the generated REST-api to retrieve ALL instances of an object, insted of only the first 20,30,40 etc?
I find that since i am using pagination for my entity-creation and management, when i want to utilize these entities in other views (self created), then the API does not provide all the instances when calling the entity.query() in angular/js.
Is this a limitation to JHipster, or can i call the REST-API in any other way supplying info to discard the paginator?
You can modify existing rest controller for that entity. Here is an example with a Center entity.
I return all centers if there is no value for offset and limit.
#RequestMapping(value = "/centers",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<List<Center>> getAll(#RequestParam(value = "page" , required = false) Integer offset,
#RequestParam(value = "per_page", required = false) Integer limit)
throws URISyntaxException {
if(offset == null && limit == null) {
return new ResponseEntity<List<Center>>(centerRepository.findAll(), HttpStatus.OK);
} else {
Page<Center> page = centerRepository.findAll(PaginationUtil.generatePageRequest(offset, limit));
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/centers", offset, limit);
return new ResponseEntity<List<Center>>(page.getContent(), headers, HttpStatus.OK);
}
}
Then in angular, you just have to call Center.query(); without params.
It's an old question but for anyone who's looking for easy solution. You need to override default PageableHandlerMethodArgumnetResolver bean:
#Configuration
public class CustomWebConfigurer implements WebMvcConfigurer {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
resolver.setFallbackPageable(Pageable.unpaged());
argumentResolvers.add(resolver);
}
}
Related
I would like to convert a parameter and then call second method with this parameter.
The convention would be that there is always the same method overloaded with the specific type. The idea is to solve it with Spring AOP.
#Component
public class ExampleAspect {
#Around( "#annotation(Example)" )
public Object test( final ProceedingJoinPoint joinPoint ) throws Throwable {
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
final Method method = signature.getMethod();
final Example example = method.getAnnotation( Example.class );
final Object[] args = joinPoint.getArgs();
final String test = args[example.value()].toString();
final Bar bar = convertToBar(test)
args[example.value()] = bar;
//ReflectionUtils?
// call getBar(Bar bar)
//return joinPoint.proceed( args );
}
}
Here is the service
#Example(0)
public Object getBar(String test) {}
public Object getBar(Bar test) {}
Are there any better options or ideas?
EDIT:
Cannot inject the target bean, because this AOP should be used by more than specific target bean.
1 possible solution not sure if there is a smarter solution
#Around("#annotation(Example)")
public Object test(final ProceedingJoinPoint joinPoint) throws Throwable {
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
final Method method = signature.getMethod();
final Example example = method.getAnnotation(Example.class);
final Object[] args = joinPoint.getArgs();
final String bar = args[example.value()].toString();
final Bar aspectModelUrn = convertFromStringToBar(bar);
args[example.value()] = bar;
final Class<?>[] parameterTypes = method.getParameterTypes();
parameterTypes[example.value()] = Bar.class;
final Method newMethod = ReflectionUtils.findMethod(joinPoint.getTarget().getClass(), method.getName(), parameterTypes);
if (newMethod == null) {
throw new IllegalArgumentException("There is no method blubb. Have you forget to create the delegate method");
}
return newMethod.invoke(joinPoint.getTarget(), args);
}
Following code would provide a handle to the annotation and the target bean (for example , here TestComponent)
A call to the TestComponent.getBar() annotated with #Example would be intercepted and advised.
#Aspect
#Component
public class ExampleAspect {
#Around("#annotation(example) && target(bean)")
public Object test(final ProceedingJoinPoint joinPoint,Example example,TestComponent bean) throws Throwable {
String value = String.valueOf(example.value());
Bar bar = convertToBar(value);
bean.getBar(bar);
return joinPoint.proceed();
}
}
Do go through Spring AOP documentation : Passing Parameters to Advice for more details.
Note : For better performance it is a good idea to limit the scope of the expression as follows.
#Around("#annotation(example) && within(com.xyz.service..*) && target(bean)")
where com.xyz.service..* will limit the expression scope only to the beans with in the package com.xyz.service..* and its sub-packages.
I am implementing Circuit breaker using Hystrix in my Spring boot application, my code is something like below:
#service
public class MyServiceHandler {
#HystrixCommand(fallbackMethod="fallback")
public String callService() {
// if(remote service is not reachable
// throw ServiceException
}
public String fallback() {
// return default response
}
}
// In application.properties, I have below properties defined:
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
hystrix.command.default.circuitBreaker.requestVolumeThreshold=3
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=30000
hystrix.threadpool.default.coreSize=4
hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds=200000
I see that the fallback() is getting called with each failure of callService(). However, the circuit is not opening after 3 failures. After 3 failures, I was expecting that it will directly call fallback() and skip callService(). But this is not happening. Can someone advise what I am doing wrong here?
Thanks,
B Jagan
Edited on 26th July to add more details below:
Below is the actual code. I played a bit further with this. I see that the Circuit opens as expected on repeated failured when I call the remote service directly in the RegistrationHystrix.registerSeller() method. But, when I wrap the remote service call within Spring retry template, it keeps going into fallback method, but circuit never opens.
#Service
public class RegistrationHystrix {
Logger logger = LoggerFactory.getLogger(RegistrationHystrix.class);
private RestTemplate restTemplate;
private RetryTemplate retryTemplate;
public RegistrationHystrix(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
retryTemplate = new RetryTemplate();
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(1000l);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
retryTemplate.setRetryPolicy(retryPolicy);
}
#HystrixCommand(fallbackMethod = "fallbackForRegisterSeller", commandKey = "ordermanagement")
public String registerSeller(SellerDto sellerDto) throws Exception {
String response = retryTemplate.execute(new RetryCallback<String, Exception>() {
#Override
public String doWithRetry(RetryContext context) {
logger.info(String.format("Retry count %d", context.getRetryCount()));
return restTemplate.postForObject("/addSeller", sellerDto, String.class);
}
});
return response;
}
public List<SellerDto> getSellersList() {
return restTemplate.getForObject("/sellersList", List.class);
}
public String fallbackForRegisterSeller(SellerDto sellerDto, Throwable t) {
logger.error("Inside fall back, cause - {}", t.toString());
return "Inside fallback method. Some error occured while calling service for seller registration";
}
}
Below is the service class which in turn calls the above Hystrix wrapped service. This class in turn is invoked by a controller.
#Service
public class RegistrationServiceImpl implements RegistrationService {
Logger logger = LoggerFactory.getLogger(RegistrationServiceImpl.class);
private RegistrationHystrix registrationHystrix;
public RegistrationServiceImpl(RegistrationHystrix registrationHystrix) {
this.registrationHystrix = registrationHystrix;
}
#Override
public String registerSeller(SellerDto sellerDto) throws Exception {
long start = System.currentTimeMillis();
String registerSeller = registrationHystrix.registerSeller(sellerDto);
logger.info("add seller call returned in - {}", System.currentTimeMillis() - start);
return registerSeller;
}
So, I am trying to understand why the Circuit breaker is not working as expected when using it along with Spring RetryTemplate.
You should be using metrics.healthSnapshot.intervalInMilliseconds while testing. I guess you are executing all 3 request within default 500 ms and hence the circuit isn't getting open. You can either decrease this interval or you may put a sleep between the 3 requests.
To get the file size of an URL without download, I wrote:
public static long getFileSizeWithoutDownload(String url) {
ConnectionRequest cr = new GZConnectionRequest();
cr.setUrl(url);
cr.setPost(false);
NetworkManager.getInstance().addProgressListener((NetworkEvent evt) -> {
if (cr == evt.getConnectionRequest() && evt.getLength() > 0) {
cr.kill();
}
});
NetworkManager.getInstance().addToQueueAndWait(cr);
return cr.getContentLength();
}
It seems to work on Simulator, Android and iOS with a testing URL of my Spring Boot server.
Anyway, I consider this code as a workaround, as I couldn't find an API that directly gives me the file size without starting the download first. Starting the download and then killing it works, but maybe there may be a better way to get the same result. By the way, the condition && evt.getLength() > 0 may never be satisfied in some cases (depending on the headers received), so it would be better to read only the headers, in which "Content-Length" may be present or absent.
So, my question is if, with Codename One, there is a way to download only the response headers, without starting the download. Thank you.
Using the HTTP head request should give you the content length header that you can then use to get the size of the file without triggering a download. Your code might not follow through on the download but it does physically happen so a head request would be superior.
Unfortunately while there's a nice wrapper to head in Rest. This wrapper isn't very useful since there's no API to query response headers. That would make sense as an enhancement. You would need to derive ConnectionRequest and read the server response headers to get the content length.
Thank you Shai, your answer https://stackoverflow.com/a/62124902/1277576 led me in the right direction. cr.setHttpMethod("HEAD"); simplifies the code and prevents the download from starting:
public static long getFileSizeWithoutDownload(String url) {
ConnectionRequest cr = new GZConnectionRequest();
cr.setUrl(url);
cr.setHttpMethod("HEAD");
cr.setPost(false);
NetworkManager.getInstance().addToQueueAndWait(cr);
return cr.getContentLength();
}
However, as you wrote, I can override ConnectionRequest for a more precise control of the headers. This other method performs the same function as the previous one, but it also guarantees me that the server supports partial downloads. In fact, if the server does not support partial downloads, the information about the content length would be useless for my purposes:
/**
* Returns -2 if the server doesn't accept partial downloads, -1 if the
* content length is unknow, a value greater than 0 if the Content-Length is
* known
*
* #param url
* #return must be interpreted as a boolean value: if greater than zero than
* partial downloads are supported (the returned value is the Content-Length),
* otherwise they are not supported.
*/
public static long getFileSizeWithoutDownload(String url) {
// documentation about the headers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
Wrapper<Long> result = new Wrapper<>(0l);
ConnectionRequest cr = new GZConnectionRequest() {
#Override
protected void readHeaders(Object connection) throws IOException {
String acceptRanges = getHeader(connection, "Accept-Ranges");
if (acceptRanges == null || !acceptRanges.equals("bytes")) {
Log.p("The partial downloads of " + url + " are not supported.", Log.WARNING);
result.set(-2l);
} else {
String contentLength = getHeader(connection, "Content-Length");
if (contentLength != null) {
result.set(Long.parseLong(contentLength));
} else {
Log.p("The Content-Length of " + url + " is unknown.", Log.WARNING);
result.set(-1l);
}
}
}
};
cr.setUrl(url);
cr.setHttpMethod("HEAD");
cr.setPost(false);
NetworkManager.getInstance().addToQueueAndWait(cr);
return result.get();
}
The readHeaders and getHeader methods are implementation dependent. I have verified that they work as desired on Simulator, Android and iOS.
Lastly, the Wrapper class is so implemented:
/**
* Generic object wrapper, as workaround for the issue "Local variables
* referenced from a lambda expression must be final or effectively final".
*/
public class Wrapper<T> {
private T object;
public Wrapper(T obj) {
this.object = obj;
}
public T get() {
return object;
}
public void set(T obj) {
this.object = obj;
}
}
I hope this detailed answer will help those who need to read HTTP headers with Codename One.
I read where someone was able to do this, but I'm having a hard time getting it to work.
Basically, I'm scheduling an HTTP callout to a page that has a controller that builds a CSV and emails it to a recipient.
The Scheduled class:
global class ReportExporter implements System.Schedulable {
global void execute(SchedulableContext sc) {
getmailReportOutput ex = new getmailReportOutput();
ex.exportCSV();
}
}
The getEmailReportOutput class:
public class getmailReportOutput{
public Static String strSessionID;
public getmailReportOutput() {
}
public void exportCSV() {
makeReportRequest();
}
#future (callout=true)
public Static void makeReportRequest() {
strHost ='c.cs4.visual.force.com';
strSessionID = UserInfo.getSessionId();
String requestUrl = 'https://' + strHost + '/apex/TestSendReport#';
HttpRequest req = new HttpRequest();
req.setEndpoint(requestUrl);
req.setMethod('GET');
req.setHeader('Cookie','sid=' + strSessionID );
String output = new Http().send(req).getBody();
System.debug('HTTP RESPONSE RETURNED: ' + output);
}
}
The getEmailReportOutput class does an HTTP Callout to a VF page: I make sure to send the sessionID with the request:
And the "TestSendReport" is just a simple callout to a controller:
<apex:page controller="Exporter" action="{!runrpt}">
</apex:page>
...And the controller is calling the report content:
public class Exporter {
public static Boolean isTest;
public static String strEmailAddr;
public void runrpt() {
executeRpt();
}
#future
public static void executeRpt() {
System.debug('CALLING REPORT EXPORTER...');
String ReportName__c = '00OP0000000Jp3N';
String strEmailAddr = 'myname#email.com';
ApexPages.PageReference report = new ApexPages.PageReference( '/' + RptName__c + '?csv=1');
Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment();
attachment.setFileName('report.csv');
attachment.setBody(report.getContent());
attachment.setContentType('text/csv');
Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage();
message.setFileAttachments(new Messaging.EmailFileAttachment[] { attachment } );
message.setSubject('Report');
message.setPlainTextBody('The report is attached.');
message.setToAddresses( new String[] { strEmailAddr } );
Messaging.sendEmail( new Messaging.SingleEmailMessage[] { message } );
}
}
...Any ideas? The debug logs show all is well, but nothing is received. I know this is a wall of code, but it seems to be what people recommend to accomplish the task - I just can't see anything wrong.
I don't see anything obviously missing here :/
Just to be safe - getEmailReportOutput & getmailReportOutput are the same class (typo error in the post, not in your actual code)?
This looks like jumping a lot of hops, do I read it correctly that it's scheduled class -> REST callout -> VF page with action -> #future -> send an email? Geez, a lot can go wrong here ;) I've read somewhere that SF will keep some kind of reference counter and calling out to same instance might block you from using page.getContent...
Can you see the report body System.debug(report.getContent().toString());? Can you try saving this email as task for your own user or under a sample Account for example (setSaveAsActivity())?
As blatant plug as it is - I've used different path to solve similar requirement. Check out https://salesforce.stackexchange.com/questions/4303/scheduled-reports-as-attachment and see if you can get it to work?
I am developing a GWT app for the Google Apps marketplace. I am using AppEngine with Restlet on the server side. Client side I use the GWT edition of Restlet. This is a great combination. I have my domain objects shared between client and server and as such no need for DTO's or proxies and so on. On the client side I can simply call Restlet resources :
CustomerResourceProxy customerResource = GWT.create(CustomerResourceProxy.class);
customerResource.getClientResource().setReference("/customer");
customerResource.retrieve(new Result<Customer>() { .... }
No need to parse the underlying XML or use JSNI to interpret incoming JSON.
BUT... part of the app is a GMAIL contextual gadget, and I cannot simply use the above code because all communication between a Gadget and the server must pass through GadgetsIO makeRequest.
So... just for the gadget, I will have to make the effort of parsing the XML or using JSNI to interpret the incoming JSON.
Is it überhaupt possible to hack the Restlet GWT client to pass all communication via GadgetsIO and what would it take ? Any pointers very welcome !
K.
I managed to get Restlet resources to work within a Gadget using GWT by making some changes to the Restlet GWT edition :
In GwtClientCall I replaced the standard GWT requestbuilder by the GadgetRequestBuilder (which will IoProvider.makeRequest), like this :
public GwtClientCall(GwtHttpClientHelper helper, String method, String requestUri, boolean hasEntity) {
super(helper, method, requestUri);
Reference requestRef = new Reference(requestUri);
if (requestRef.isRelative() || requestRef.getScheme().startsWith("http")) {
this.requestBuilder = new GadgetsRequestBuilder(method, requestUri);
this.requestBuilder.setTimeoutMillis(getHelper().getSocketConnectTimeoutMs());
this.responseHeadersAdded = false;
} else {
throw new IllegalArgumentException("Only HTTP or HTTPS resource URIs are allowed here");
}
}
In the gadgetsrequestbuilder, I had to make some changes so it would pass the headers in the request :
private GadgetsRequest doSend(String requestData, final RequestCallback callback) throws RequestException {
final RequestOptions options = RequestOptions.newInstance();
options.setMethodType(methodType);
if (requestData != null && requestData.length() > 0) {
options.setPostData(requestData);
}
options.setAuthorizationType(AuthorizationType.SIGNED);
options.setContentType(ContentType.DOM);
setHeaders(options);
final GadgetsRequest gadgetsRequest = new GadgetsRequest(getTimeoutMillis(), callback);
gadgetsRequest.setPending(true);
IoProvider.get().makeRequest(getUrl(), new ResponseReceivedHandler<Object>() {
public void onResponseReceived(ResponseReceivedEvent<Object> event) {
gadgetsRequest.fireOnResponseReceived(event, callback);
}
}, options);
return gadgetsRequest;
}
the gadget container by default strips the response headers, so i manually add the MediaType.APPLICATION_JAVA_OBJECT_GWT
#Override
public Series<org.restlet.client.engine.header.Header> getResponseHeaders() {
final Series<org.restlet.client.engine.header.Header> result = super.getResponseHeaders();
if (!this.responseHeadersAdded && (getResponse() != null)) {
Header[] headers = getResponse().getHeaders();
for (int i = 0; i < headers.length; i++) {
if (headers[i] != null) {
result.add(headers[i].getName(), headers[i].getValue());
}
}
result.add(HeaderConstants.HEADER_CONTENT_TYPE, MediaType.APPLICATION_JAVA_OBJECT_GWT.toString());
this.responseHeadersAdded = true;
}
return result;
}
A lot of dialogboxes for debugging later, it works :-)