I followed the blog & I was able to perform create, read & update operations on my custom OData service, but I am unable to find any blog/document for delete operation.
Please help.
There is no dedicated blog post for executing delete operations on custom OData Services but we would advise you to follow this pattern:
public class DeleteAddressCommand extends ErpCommand<Integer> {
private static final Logger logger = CloudLoggerFactory.getLogger(DeleteAddressCommand.class);
private final BusinessPartnerService service;
private final String businessPartnerId;
private final String addressId;
public DeleteAddressCommand(final BusinessPartnerService service,
final String businessPartnerId, final String addressId) {
super(HystrixUtil.getDefaultErpCommandSetter(
DeleteAddressCommand.class,
HystrixUtil.getDefaultErpCommandProperties().withExecutionTimeoutInMilliseconds(10000)));
this.service = service;
this.businessPartnerId = businessPartnerId;
this.addressId = addressId;
}
#Override
protected Integer run() throws Exception {
final BusinessPartnerAddress addressToDelete = BusinessPartnerAddress.builder()
.businessPartner(businessPartnerId)
.addressID(addressId)
.build();
final ODataDeleteResult oDataDeleteResult = service
.deleteBusinessPartnerAddress(addressToDelete)
.execute();
return oDataDeleteResult.getHttpStatusCode();
}
}
I pasted the code from this official example
Best wishes
Florian
Related
I am trying out to write data to my local Elasticsearch Docker Container (7.4.2), for simplicity I used the AbstractReactiveElasticsearchConfiguration given from Spring also Overriding the entityMapper function. The I constructed my repository extending the ReactiveElasticsearchRepository
Then in the end I used my autowired repository to saveAll() my collection of elements containing the data. However Elasticsearch doesn't write any data. Also i have a REST controller which is starting my whole process returning nothing basicly, DeferredResult>
The REST method coming from my ApiDelegateImpl
#Override
public DeferredResult<ResponseEntity<Void>> openUsageExporterStartPost() {
final DeferredResult<ResponseEntity<Void>> deferredResult = new DeferredResult<>();
ForkJoinPool.commonPool().execute(() -> {
try {
openUsageExporterAdapter.startExport();
deferredResult.setResult(ResponseEntity.accepted().build());
} catch (Exception e) {
deferredResult.setErrorResult(e);
}
}
);
return deferredResult;
}
My Elasticsearch Configuration
#Configuration
public class ElasticSearchConfig extends AbstractReactiveElasticsearchConfiguration {
#Value("${spring.data.elasticsearch.client.reactive.endpoints}")
private String elasticSearchEndpoint;
#Bean
#Override
public EntityMapper entityMapper() {
final ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(), new DefaultConversionService());
entityMapper.setConversions(elasticsearchCustomConversions());
return entityMapper;
}
#Override
public ReactiveElasticsearchClient reactiveElasticsearchClient() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(elasticSearchEndpoint)
.build();
return ReactiveRestClients.create(clientConfiguration);
}
}
My Repository
public interface OpenUsageRepository extends ReactiveElasticsearchRepository<OpenUsage, Long> {
}
My DTO
#Data
#Document(indexName = "open_usages", type = "open_usages")
#TypeAlias("OpenUsage")
public class OpenUsage {
#Field(name = "id")
#Id
private Long id;
......
}
My Adapter Implementation
#Autowired
private final OpenUsageRepository openUsageRepository;
...transform entity into OpenUsage...
public void doSomething(final List<OpenUsage> openUsages){
openUsageRepository.saveAll(openUsages)
}
And finally my IT test
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#Testcontainers
#TestPropertySource(locations = {"classpath:application-it.properties"})
#ContextConfiguration(initializers = OpenUsageExporterApplicationIT.Initializer.class)
class OpenUsageExporterApplicationIT {
#LocalServerPort
private int port;
private final static String STARTCALL = "http://localhost:%s/open-usage-exporter/start/";
#Container
private static ElasticsearchContainer container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:6.8.4").withExposedPorts(9200);
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(final ConfigurableApplicationContext configurableApplicationContext) {
final List<String> pairs = new ArrayList<>();
pairs.add("spring.data.elasticsearch.client.reactive.endpoints=" + container.getContainerIpAddress() + ":" + container.getFirstMappedPort());
pairs.add("spring.elasticsearch.rest.uris=http://" + container.getContainerIpAddress() + ":" + container.getFirstMappedPort());
TestPropertyValues.of(pairs).applyTo(configurableApplicationContext);
}
}
#Test
void testExportToES() throws IOException, InterruptedException {
final List<OpenUsageEntity> openUsageEntities = dbPreparator.insertTestData();
assertTrue(openUsageEntities.size() > 0);
final String result = executeRestCall(STARTCALL);
// Awaitility here tells me nothing is in ElasticSearch :(
}
private String executeRestCall(final String urlTemplate) throws IOException {
final String url = String.format(urlTemplate, port);
final HttpUriRequest request = new HttpPost(url);
final HttpResponse response = HttpClientBuilder.create().build().execute(request);
// Get the result.
return EntityUtils.toString(response.getEntity());
}
}
public void doSomething(final List<OpenUsage> openUsages){
openUsageRepository.saveAll(openUsages)
}
This lacks a semicolon at the end, so it should not compile.
But I assume this is just a typo, and there is a semicolon in reality.
Anyway, saveAll() returns a Flux. This Flux is just a recipe for saving your data, and it is not 'executed' until subscribe() is called by someone (or something like blockLast()). You just throw that Flux away, so the saving never gets executed.
How to fix this? One option is to add .blockLast() call:
openUsageRepository.saveAll(openUsages).blockLast();
But this will save the data in a blocking way effectively defeating the reactivity.
Another option is, if the code you are calling saveAll() from supports reactivity is just to return the Flux returned by saveAll(), but, as your doSomething() has void return type, this is doubtful.
It is not seen how your startExport() connects to doSomething() anyway. But it looks like your 'calling code' does not use any notion of reactivity, so a real solution would be to either rewrite the calling code to use reactivity (obtain a Publisher and subscribe() on it, then wait till the data arrives), or revert to using blocking API (ElasticsearchRepository instead of ReactiveElasticsearchRepository).
I'm a newbee using Dropwizard and I'm following the tutorial in the website to create the hello world application. Can anyone please explain to me how to use NonEmptyStringParam to print something like "Hello, stranger!" if no parameter is provided to sayHello?
The following is my Resource code and it outputs:
{"id":1,"content":"Hello, Optional[Stranger]!"}
instead of
{"id":1,"content":"Hello, Stranger!"}
public class HelloWorldResource {
private final String template;
private final NonEmptyStringParam defaultName;
private final AtomicLong counter;
public HelloWorldResource(String template, String defaultName) {
this.template = template;
this.defaultName = new NonEmptyStringParam(defaultName);
this.counter = new AtomicLong();
}
#GET
#Timed
public Saying sayHello(#QueryParam("name") Optional<NonEmptyStringParam> name) {
final String value = String.format(template, name.orElse(defaultName));
return new Saying(counter.incrementAndGet(), value);
}
}
Thanks!
You shouldn't wrap the NonEmptyStringParam with Optional<>. See the testcase from the Dropwizard source.
Also remove the wrap of defaultName with NonEmptyStringParam in the constructor method.
I am not sure it is possible what I want to do. I try to improve my generic code to reduce number of parameters because theoratically only one information is needed.
Currently I have a constructor like:
protected _AbstractDataOnDemand(
final Class<T> entityClass,
final CrudService<T> service,
final ApplicationRepository<T> repository,
final JPAPersistableDODPopulationUtilizable<T> dodPopulation
){
this.entityClass = entityClass;
this.service = service;
this.repository = repository;
this.dodPopulation = dodPopulation;
}
As you can see it could be enough to give entityClass as information and create instances of service, repository, dodPopulation with that information.
I would like to do something:
protected _AbstractDataOnDemand(
final Class<T> entityClass,
){
this.entityClass = entityClass;
this.service = createCrudService(entityClass);
this.repository = createRepository(entityClass);
this.dodPopulation = createDodPopulation(entityClass);
}
Is this possible?
Using RestDocs version 1.1.1.RELEASE and SpringBoot 1.4.0.RELEASE, parameters when using "httpRequest" is documented double.
The following code:
#RunWith(SpringRunner.class)
#WebMvcTest(ProductResource.class)
#AutoConfigureRestDocs("target/generated-snippets")
public class ProductResourceDocumentation {
private static final String PROPERTY_ID_VALUE = "d7612";
private static final String SALES_MARKET_VALUE = "999";
private static final String SEASON_VALUE = "2016";
private static final String SECTIONS_VALUE = "buildings";
private static final String SHOW_DESCRIPTIONS_VALUE = "false";
private static final String STRING = "string";
private static final Integer NUMBER = 1;
private static final String NOT_FOUND = "404 Not Found";
private static final String BAD_REQUEST = "400 Bad Request";
private RestDocumentationResultHandler documentationResultHandler;
#MockBean
private ProductHandler productHandler;
#Autowired
private MockMvc mockMvc;
#Before
public void setup() {
this.documentationResultHandler = document("{class-name}/{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()));
}
#Test
public void listProducts() throws Exception {
Product product = getBasicProductsRepresentation();
when(productHandler.getProduct(PROPERTY_ID_VALUE, SALES_MARKET_VALUE, SEASON_VALUE, null, null)).thenReturn(product);
mockMvc.perform(RestDocumentationRequestBuilders.get("/products/{propertyId}", PROPERTY_ID_VALUE)
.param("salesMarket", SALES_MARKET_VALUE)
.param("season", SEASON_VALUE))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.propertyID", is(PROPERTY_ID_VALUE)))
.andExpect(jsonPath("$.season", is(SEASON_VALUE)))
.andDo(documentationResultHandler.document(
pathParameters(
parameterWithName("propertyId").description(PATH_PARAM__PROPERTY_ID)
),
requestParameters(
parameterWithName("salesMarket").description(REQUEST_PARAM__SALES_MARKET),
parameterWithName("season").description(REQUEST_PARAM__SEASON)
),
httpRequest(), httpResponse()
));
}
Produces the following documentation ("salesMarket=999&season=2016" is documented twice):
GET /products/d7612? salesMarket=999&season=2016&salesMarket=999&season=2016 HTTP/1.1
Have anybody experienced anything similar or know what the problem is?
It's a bug that's been fixed in 1.1.2.RELEASE. Upgrading will resolve the problem. When upgrading make sure that you get 1.1.2 of both spring-restdocs-mockmvc and spring-restdocs-core. The latter module is where the fix is.
We get "double documentation" when we set a query param (see block below) to an empty string (""):
GET /Thing/OtherThing/Foo/?thinger=FOO&block=&bla=5&block= HTTP/1.1
We use Spring Boot 1.5.2 and Spring REST Docs 1.1.2.RELEASE.
I am trying to use spring data mongodb to retrieve a list of collections from the DB. However as soon as my code runs I get the following exception:
org.springframework.data.mapping.model.MappingException: No mapping metadata found for java.lang.String
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:209)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1008)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$100(MappingMongoConverter.java:75)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:957)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:924)
at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:78)
at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:63)
at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:70)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:232)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:212)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:176)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:172)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:75)
I can't seem to find the solution for this anywhere. Any help would be highly appreciated
Here is my java code which is used to retrieve the data:
public List<GateAppointment> listGateAppointments() {
List<GateAppointment> gateAppointments = null;
try{
MongoOperations mongoOperation = (MongoOperations)getMongoTemplate();
gateAppointments = mongoOperation.findAll(GateAppointment.class,COLLECTION_NAME);
}
catch(Exception e){
e.printStackTrace();
}
return gateAppointments;
}
And public static final String COLLECTION_NAME = "gateVisitAppointments";
The following is a sample of my DB data(Sorry, cant post image directly as I dont have 10 rep):
Please click to view DB Image
Following is my GateAppointment class file properties (The rest of the file has all the setters and getters):
package com.ig.avs.common.entity.db;
public class GateAppointment {
/**
* The Class GateAppointment.
*
*/
private String gate;
private String gateAppointmentNbr;
private String bol;
private String containerNbr;
private String iso;
private String line;
private String transactionType;
private String truckingCompany;
private String truckId;
private String appoinmentDate;
private String apSlot;
private String slotStartTime;
private String slotEndTime;
private String isMapped;
private String status;