I'm trying to load data into the database from a file when the application starts. The file mapping to the list of entities works fine, but when I call saveAll method I get a strange error -
Audit4j:ERROR Your Java version (13.0.2) is not supported for Audit4j. see http://audit4j.org/errors#javaVersion for further details. Audit4j:ERROR Failed to initialize Audit4j: Java version is not supported.
I changed the version, error remained the same, and what does Java version have to do with it, if logging works fine without call to saveAll.
I already have the functionality to load data through the controller, and tried to load same file through it - everything works fine. What can be the cause of problem?
Code:
#Component
#AllArgsConstructor
public class MetaLoader {
private final ResourceLoader resourceLoader;
private EntityMetaRepository entityMetaRepository;
#PostConstruct
public void init() throws IOException {
Resource metaResource = resourceLoader.getResource("classpath:metadata/metadata.json");
log.info("**MetaLoader | resource exists?=" + metaResource.exists());
File metaFile = metaResource.getFile();
// mapping
ObjectMapper mapper = new ObjectMapper();
List<Meta> metaList;
CollectionType metaListType = mapper.getTypeFactory()
.constructCollectionType(List.class, Meta.class);
metaList= mapper.readValue(metaFile, metaListType);
log.info("**MetaLoader | metaList=" + metaList.toString());
if (!metaList.isEmpty()) {
log.info("**MetaLoader | saving metadata...");
List<EntityMeta> entityMetaList = metaList.stream().map(EntityMeta::new)
.collect(Collectors.toUnmodifiableList());
try {
entityMetaRepository.saveAll(entityMetaList);
} catch (EntityExistsException e) {
log.error("**MetaLoader | something went wrong=" + e.getMessage() + "\n" + e.getCause());
}
}
Controller
#Controller
public class MetaApi {
#Autowired private EntityMetaRepository entityMetaRepository;
#PostMapping(value = "/meta", consumes = "multipart/form-data")
public ResponseEntity<ErrorResponse> postMetaTableFile(MultipartFile file) {
ObjectMapper mapper = new ObjectMapper();
List<Meta> metaList = null;
try {
CollectionType metaListType = mapper.getTypeFactory()
.constructCollectionType(List.class, Meta.class);
metaList = mapper.readValue(file.getBytes(), metaListType);
} catch (IOException e) {
ErrorResponse response = new ErrorResponse().code(400).type("BAD REQUEST").message("Malformed file");
e.printStackTrace();
}
try {
List<EntityMeta> entityMetaList = metaList.stream().map(EntityMeta::new)
.collect(Collectors.toUnmodifiableList());
entityMetaRepository.saveAll(entityMetaList);
} catch (EntityExistsException e) {
throw new ResponseException(e.getMessage(),HttpStatus.BAD_REQUEST);
}
ErrorResponse response = new ErrorResponse().code(200).type("OK").message("OK");
return ResponseEntity.ok(response);
}
}
Related
I have a Java service that queries the database and returns a list of data which I must show in a table in my front with angular, so I did this method that returns a hash map to know if an error occurred when querying or to know that there is no data in the date range so it returns an error code since I want to validate this code in the front and show a message in my front that there is no data or that an error occurred in addition to showing the
Java Controller
#CrossOrigin(origins = "http://localhost:4200")
#RestController
#RequestMapping("/consultValues")
public class ValuesController {
#GetMapping
public Map<String, Object> consultValues(
#RequestParam(required = false, value = "startDate") Integer startDate,
#RequestParam(required = false, value = "endDate") Integer endDate) throws Exception {
Map<String, Object> listValues = new HashMap<>();
try {
listValues = valuesService.listValues(startDate, endDate);
} catch (Exception e) {
LOGGER.error("Error in Values ");
throw e;
}
return listValues;
}
}
Java Service
#Override
public Map<String, Object> listValues(Integer startDate, Integer endDate) throws Exception {
Map<String, Object> response = new HashMap<>();
List<ValuesDto> list = new ArrayList<ValuesDto>();
try {
Integer start = startDate;
Integer end = endDate;
list = valuesRepository.findByDates(start, end);
if (list.isEmpty() || list == null) {
LOGGER.error("There is not values");
response.put("Error", 400);
}
} catch (Exception e) {
LOGGER.error("An error ocurred");
response.put("Error", 500);
response.put("error", e.getMessage());
throw e;
}
response.put("success", true);
response.put("data", list);
return response;
}
Now in my front I have this method of my service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import {ValoresDto} from '../Models/ValoresDTO';
#Injectable({
providedIn: 'root'
})
export class ConsultValuesService {
constructor(private http: HttpClient) { }
Url = 'http://localhost:8080/consultValues';
consultValues(startDate:any, endDate:any){
return this.http.get<ValuesDTO[]>(this.Url+ `?startDate=${startDate}&endDate=${endDate}`);
}
}
In my Component.ts I have this method but I dont know how to validate the response of my java service, for example if my java service returns a code error 400 means that there is not data and show a message with Swal, if returns 500 ocurred an error and show the message with Swal too, or sucees return the list and fill my table
getValuesDB() {
if (this.valuesForm.valid) {
this.service.consultValues(this.endDate, this.endDate).subscribe({
next: data => {
this.modelConsultValues=data;
},
error: (err) => console.error(err),
complete: () => console.log('Completed')
});
} else {
Swal.fire({
icon: 'error',
text: 'You must select both dates'
})
}
}
anyone helps me please, how can I validate the response of my java service and show the table fill or the messages
This is highly opinionated but I will post a link anyway. class-validator let's you spice up models with decorators and then validate the instances.
https://github.com/typestack/class-validator
I have below java code where i am trying to fetch data using select query and then import this data into json format.
The problem is currently i am getting error
ORA-02063: preceding line from ABSTP
; nested exception is java.sql.SQLException:
ORA-01555: snapshot too old: rollback segment number 14 with name "_SYSSMU14_1823253467$" too small
This error i believe is because of long running query. As i am not good in java so i would like to know is there any other process in java for transaction handling where i can distribute the transaction and run this query or is there any other way where i can handle such transactions in java code to avoid this issue?
#Service
public class InformerSupp {
public final static Logger log = LoggerFactory.getLogger(InformerSupp.class);
#Autowired
private NamedParameterJdbcTemplate NamedParameterJdbcTemplate;
#Autowired
private String queueName;
#Autowired
private JmsTemplate jmsTemplate;
private ObjectMapper mapper;
#PostConstruct
public void afterPropertiesSet() throws Exception {
mapper = new ObjectMapper();
}
public boolean transportData() {
final List<Map<String, Object>> maps = NamedParameterJdbcTemplate
.queryForList(format("select * from isi_trt c"),EMPTY_MAP);
for (Map<String, Object> entry : maps) {
String json = null;
try {
json = mapper.writeValueAsString(entry);
transportMessage(json);
} catch (JMSException e) {
log.error(String.format("Failed to create a JSON message : %s", entry), e);
return false;
} catch (JsonProcessingException e) {
log.error(String.format("Failed to transport message : %s to %s", json, queueName), e);
return false;
}
}
return true;
}
private void transportMessage(final String json) throws JMSException {
log.info(String.format("send message : %s ",json));
jmsTemplate.send(queueName, session -> {
TextMessage textMessage = session.createTextMessage();
int ccsid = _L.coalesce(((MQSession) session).getIntProperty(WMQ_QMGR_CCSID),0);
textMessage.setIntProperty(WMQ_CCSID, ccsid);
textMessage.setIntProperty(JMS_IBM_CHARACTER_SET, ccsid);
textMessage.setText(json);
return textMessage;
});
}
}
I've made method that I use to edit Item from database.
This is how my method looks:
public Product editProduct(PrimaryKey primaryKey, Product content) {
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withValueMap(createValueMap(content));
UpdateItemOutcome itemOutcome = databaseController.getTable(PRODUCT_TABLE).updateItem(updateItemSpec);
return convertToProduct(itemOutcome);
}
private Map<String, Object> createValueMap(Product content) {
Map<String, Object> result = new HashMap<>();
result.put("name", content.getName());
result.put("calories", content.getCalories());
result.put("fat", content.getFat());
result.put("carbo", content.getCarbo());
result.put("protein", content.getProtein());
result.put("productKinds", content.getProductKinds());
result.put("author", content.getAuthor());
result.put("media", content.getMedia());
result.put("approved", content.getApproved());
return result;
}
private Product convertToProduct(UpdateItemOutcome itemOutcome) {
Product product = new Product();
product.setName(itemOutcome.getItem().get("name").toString());
product.setCalories(itemOutcome.getItem().getInt("calories"));
product.setFat(itemOutcome.getItem().getDouble("fat"));
product.setCarbo(itemOutcome.getItem().getDouble("carbo"));
product.setProtein(itemOutcome.getItem().getDouble("protein"));
product.setProductKinds(itemOutcome.getItem().getList("productKinds"));
ObjectMapper objectMapper = new ObjectMapper();
try {
Author productAuthor = objectMapper.readValue(itemOutcome.getItem().getString("author"), Author.class);
product.setAuthor(productAuthor);
} catch (IOException e) {
e.printStackTrace();
}
try {
Media productMedia = objectMapper.readValue(itemOutcome.getItem().getString("media"), Media.class);
product.setMedia(productMedia);
} catch (IOException e) {
e.printStackTrace();
}
return product;
}
Now I want to create endpoint class for this method but I have problem, I need to get primarykey as parameter (it's looks like this for example: 2567763a-d21e-4146-8d61-9d52c2561fc0) and I don't know how to do this.
At the moment my class looks like that:
public class EditProductLambda implements RequestHandler<Map<String, Object>, ApiGatewayResponse> {
private LambdaLogger logger;
#Override
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
logger = context.getLogger();
logger.log(input.toString());
try{
Product product = RequestUtil.parseRequest(input, Product.class);
//PrimaryKey primaryKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
KitchenService kitchenService = new KitchenService(new DatabaseController(context, Regions.EU_CENTRAL_1), logger);
Product editedProduct = kitchenService.editProduct(primaryKey, product);
return ResponseUtil.generateResponse(HttpStatus.SC_CREATED, editedProduct);
} catch (IllegalArgumentException e){
return ResponseUtil.generateResponse(HttpStatus.SC_BAD_REQUEST, e.getMessage());
}
}
Can someone give me some advice how to do that? Or maybe my method is done wrong?
So first you have to create a trigger to Lambda function and ideal prefer here would be an API gateway. You can pass your data as query string or as a request body to API gateway.
You can use body mapping template in the integration request section of API gateway and get request body/query string. Construct a new json at body mapping template, which will have data from request body/query string. As we are adding body mapping template your business logic will get the json we have constructed at body mapping template.
Inside body mapping template to get query string please do ,
$input.params('querystringkey')
For example inside body mapping template (If using query string),
#set($inputRoot = $input.path('$'))
{
"primaryKey" : "$input.params('$.primaryKey')"
}
if passing data as body then,
#set($inputRoot = $input.path('$'))
{
"primaryKey" : "$input.path('$.primaryKey')"
}
Please read https://aws.amazon.com/blogs/compute/tag/mapping-templates/ for more details on body mapping template
<soapenv:Fault xmlns:m="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode>m:Server</faultcode>
<faultstring>someFaultString</faultstring>
<detail>
<NS1:confirmIdentityErrorInfo xmlns:NS1="example.com">
<faultInfo>
<faultType>Business Exception</faultType>
<faultCode>100</faultCode>
<message>some message</message>
<faultState>fault state</faultState>
</faultInfo>
</NS1:confirmIdentityErrorInfo>
</detail>
</soapenv:Fault>
I would need to generate the fault object as above. I am able to generate 'confirmIdentityErrorInfo' but not able to add child elements. I tried this option, but I couldn't generated nested object structure.
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public SoapFaultMappingExceptionResolver exceptionResolver(){
SoapFaultMappingExceptionResolver exceptionResolver = new DetailSoapFaultDefinitionExceptionResolver();
SoapFaultDefinition faultDefinition = new SoapFaultDefinition();
faultDefinition.setFaultCode(SoapFaultDefinition.SERVER);
exceptionResolver.setDefaultFault(faultDefinition);
Properties errorMappings = new Properties();
errorMappings.setProperty(Exception.class.getName(), SoapFaultDefinition.SERVER.toString());
errorMappings.setProperty(BusinessException.class.getName(), SoapFaultDefinition.SERVER.toString());
exceptionResolver.setExceptionMappings(errorMappings);
exceptionResolver.setOrder(1);
return exceptionResolver;
}
}
protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) {
if (ex instanceof BusinessException) {
SoapFaultDetail detail = fault.addFaultDetail();
try
{
QName entryName = new QName("namespace", "confirmIdentityErrorInfo", "NS1");
detail.addFaultDetailElement(entryName);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
But I am not sure how to add child elements to QName. Can someone help me how to product the fault detail as shown above?
This is the solution.
fault.addFaultDetail();
this.marshaller.marshal(((AJAXB2MarshalledBusinessException)ex).getMyJAXB2MarshallableComplexMessage(), fault.getFaultDetail().getResult());
More detailed in this link:
public class DetailSoapFaultDefinitionExceptionResolver extends SoapFaultMappingExceptionResolver {
private static final ObjectFactory FACTORY = new ObjectFactory();
private final Marshaller marshaller;
public DetailSoapFaultDefinitionExceptionResolver() throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance("your.schema");
this.marshaller = jaxbContext.createMarshaller();
}
#Override
protected void customizeFault(Object endpoint, Exception e, SoapFault fault) {
YourFault xsdFault = new YourFault();
xsdFault.setCode("UNKNOWN_FAILURE");
xsdFault.setDescription(e.getMessage());
SoapFaultDetail faultDetail = fault.addFaultDetail();
try {
marshaller.marshal(FACTORY.createSubscriptionManagementFault(xsdFault), faultDetail.getResult());
} catch (JAXBException e1) {
log.error("Could not marshall SubscriptionManagementFault", e);
}
}
Here is detailed explanation
https://maarten.mulders.it/2018/07/custom-soap-faults-using-spring-ws/
I am trying to use CDI, using #Inject for dependency injection but my object stays null and won't initialize... more precisely:
I have a webapplication with WeatherController which use a java application with all my modules. In the Java application I have a ForecastService where I try to initialize my repositories with CDI without success.
I tried/searched a lot. Hopefully somebody can help me here?
I have a web application which uses this controller:
#Path("/weather")
public class WeatherController {
private ForecastService forecastService;
//private ForecastRepository forecastRepository = new ForecastFakeDB();
//private ObservationRepository observationRepository = new ObservationFakeDB();
public WeatherController() {
//this.forecastService.setForecastRepository(forecastRepository);
//forecastService.setObservationRepository(observationRepository);
forecastService = new ForecastService();
}
//localhost:8080/DA_project_weatherPredictions/api/weather/observation/Leuven
#GET
#Produces({"application/json"})
#Path("/observation/{location}")
public Response getObservation(#PathParam("location") String location) {
try {
ObjectMapper mapper = new ObjectMapper();
Observation observation = forecastService.getCurrentObservation(location);
//Object to JSON in String
String jsonInString = mapper.writeValueAsString(observation);
return Response.status(200).entity(jsonInString).build();
} catch (Exception ex) {
System.out.println("error");
System.out.println(ex.getMessage());
ex.printStackTrace();
return null;
}
}
This works perfectly. This is my forecastService:
public class ForecastService implements Service {
#Inject
ForecastRepository forecastRepository;
#Inject
ObservationRepository observationRepository;
private Client client;
private WebTarget webTargetObservation, webTargetForecast;
public ForecastService() {
// WeatherRepositoryFactory weatherRepositoryFactory = new WeatherRepositoryFactory();
// forecastRepository = weatherRepositoryFactory.getForecastRepository(repository);
// observationRepository = weatherRepositoryFactory.getObservationRepository(repository);
loadWeather();
}
public void setForecastRepository(ForecastRepository forecastRepository) {
this.forecastRepository = forecastRepository;
}
public void setObservationRepository(ObservationRepository observationRepository) {
this.observationRepository = observationRepository;
}
public void loadWeather() {
//http://api.openweathermap.org/data/2.5/weather?units=metric&appid=12fa8f41738b72d954b6758d48e129aa&q=BE,Leuven
//http://api.openweathermap.org/data/2.5/forecast?units=metric&appid=12fa8f41738b72d954b6758d48e129aa&q=BE,Leuven
client = ClientBuilder.newClient();
webTargetObservation = client.target("http://api.openweathermap.org/data/2.5/weather")
.queryParam("mode", "json")
.queryParam("units", "metric")
.queryParam("appid", "12fa8f41738b72d954b6758d48e129aa");
webTargetForecast = client.target("http://api.openweathermap.org/data/2.5/forecast")
.queryParam("mode", "json")
.queryParam("units", "metric")
.queryParam("appid", "12fa8f41738b72d954b6758d48e129aa");
}
public Observation getCurrentObservation(String location) throws Exception {
Observation observation;
observation = observationRepository.getObservation(location);
if (observation == null) {
try {
//observation = webTargetObservation.queryParam("q", location).request(MediaType.APPLICATION_JSON).get(Observation.class);
Response response = webTargetObservation.queryParam("q", location).request(MediaType.APPLICATION_JSON).get();
String json = response.readEntity(String.class);
//System.out.println(json);
response.close();
observation = new ObjectMapper().readValue(json, Observation.class);
//System.out.println(observation.getWeather().getDescription());
}
catch (Exception e){
StringBuilder sb = new StringBuilder(e.toString());
for (StackTraceElement ste : e.getStackTrace()) {
sb.append("\n\tat ");
sb.append(ste);
}
String trace = sb.toString();
throw new Exception (trace);
//throw new Exception("Location not found");
}
this.observationRepository.addObservation(observation, location);
}
return observation;
}
So the problem is that my repositories stay null
#Alternative
public class ObservationDB implements ObservationRepository{
//as ID we can use the ASCI value of the String key .. example uklondon to ASCII
public ObservationDB(String name) {
}
#Override
public Observation getObservation(String location) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void addObservation(Observation observation, String location) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Mermory DB:
#Default
public class ObservationFakeDB implements ObservationRepository {
//example String key : beleuven, uklondon
private static Map<String, Observation> observations;
public ObservationFakeDB() {
observations = new HashMap<>();
}
#Override
public Observation getObservation(String location) {
return observations.get(location);
}
#Override
public void addObservation(Observation observation, String location) {
observations.put(location, observation);
}
}
I have a beans.xml, I thought beans.xml, #Inject, #Default en #Alternative would make this work. I tried #Dependent, #Applicationscoped.
EDIT:
I also often get this warning on Netbeans.
My beans.xml
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
You need to let your CDI container manages the lifecycle of all your beans to allow it to resolve and inject properly their dependencies.
So, in your case you should not create yourself the instance of ForecastService, you should rather delegate it to the CDI container by simply annotating the field forecastService with #Inject this way its dependencies will be automatically resolved and set by the container.
public class WeatherController {
#Inject
private ForecastService forecastService;
...