EclipseLink Moxy unmarshall and getValueByXPath gives null - xpath

I use the below code to get unmarshall and query the unmarshelled object by Xpath.
I am able to get the object after unmarshalling, but while querying by XPath, the value is coming as null.
Do I need to specify any NameSpaceResolver?
Please let me know if you are looking for any further information.
My code:
JAXBContext jaxbContext = (JAXBContext) JAXBContextFactory.createContext(new Class[] {Transaction.class}, null);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StreamSource streamSource= new StreamSource(new StringReader(transactionXML));
transaction = unmarshaller.unmarshal(streamSource, Transaction.class).getValue();
String displayValue = jaxbContext.getValueByXPath(transaction, xPath, null, String.class);
My XML:
<Transaction xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<SendingCustomer firstName="test">
</SendingCustomer>
</Transaction>

Since there are no namespaces in your example you do not need to worry about leveraging a NamespaceResolver. You didn't provide the XPath that you were having trouble with, so I have just picked one in the example below.
JAVA MODEL
Transaction
import javax.xml.bind.annotation.*;
#XmlRootElement(name="Transaction")
public class Transaction {
#XmlElement(name="SendingCustomer")
private Customer sendingCustomer;
}
Customer
import javax.xml.bind.annotation.XmlAttribute;
public class Customer {
#XmlAttribute
private String firstName;
#XmlAttribute
private String lastNameDecrypted;
#XmlAttribute(name="OnWUTrustList")
private boolean onWUTrustList;
#XmlAttribute(name="WUTrustListType")
private String wuTrustListType;
}
DEMO CODE
input.xml
<Transaction xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SendingCustomer firstName="test" lastNameDecrypted="SMITH"
OnWUTrustList="false" WUTrustListType="NONE">
</SendingCustomer>
</Transaction>
Demo
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jaxbContext = (JAXBContext) JAXBContextFactory.createContext(new Class[] {Transaction.class}, null);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StreamSource streamSource= new StreamSource("src/forum17687460/input.xml");
Transaction transaction = unmarshaller.unmarshal(streamSource, Transaction.class).getValue();
String displayValue = jaxbContext.getValueByXPath(transaction, "SendingCustomer/#firstName", null, String.class);
System.out.println(displayValue);
}
}
Output
test

Related

Testing a REST endpoint with Spring, MongoDB using ObjectIds

I'm new to MongoDB and I'm writing a series of unit tests for a Mongo-backed REST web-service. Here's a simple test for a /clients/{id} enpoint :
#RunWith(MockitoJUnitRunner.class)
public class ClientsControllerMockMvcStandaloneTest {
private MockMvc mvc;
#Mock
private ClientsRepository clientsRepository;
#Mock
private ModelMapper modelMapper;
#InjectMocks
private ClientsController clientsController;
private ExceptionHandlerExceptionResolver createExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver() {
#SuppressWarnings("ConstantConditions")
#Override
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(final HandlerMethod handlerMethod,
final Exception exception) {
final Method method = new ExceptionHandlerMethodResolver(RestResponseEntityExceptionHandler.class)
.resolveMethod(exception);
final RestResponseEntityExceptionHandler handler = new RestResponseEntityExceptionHandler();
return new ServletInvocableHandlerMethod(handler, method);
}
};
exceptionResolver.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
exceptionResolver.afterPropertiesSet();
return exceptionResolver;
}
#Before
public void setup() {
JacksonTester.initFields(this, new ObjectMapper());
mvc = MockMvcBuilders.standaloneSetup(clientsController)
.setHandlerExceptionResolvers(createExceptionResolver())
.build();
}
// GET /api/clients/{id} 200
#Test
public void findById_ClientEntryFound_ShouldReturnFoundClientEntry() throws Exception {
final ObjectId id = new ObjectId();
final Client client = Client.builder()
.id(id)
.name("Microsoft")
.build();
final ClientDTO clientDTO = ClientDTO.builder()
.id(id)
.name("Microsoft")
.build();
when(clientsRepository.findById(id))
.thenReturn(Optional.of(client));
when(modelMapper.map(client, ClientDTO.class))
.thenReturn(clientDTO);
mvc.perform(get("/clients/" + id.toString())
.accept(TestUtils.APPLICATION_JSON_UTF8))
.andExpect(content().contentType(TestUtils.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(id)))
.andExpect(jsonPath("$.name", is("Microsoft")))
.andDo(MockMvcResultHandlers.print());
verify(modelMapper, times(1)).map(client, ClientDTO.class);
verify(clientsRepository, times(1)).findById(id);
verifyNoMoreInteractions(clientsRepository);
}
}
I expect this to work but I'm getting the following :
java.lang.AssertionError: JSON path "$.id"
Expected: is <5c9b9a0289d2b311b150b92c>
but: was <{timestamp=1553701378, machineIdentifier=9032371, processIdentifier=4529, counter=5290284, timeSecond=1553701378, time=1553701378000, date=1553701378000}>
Expected :is <5c9b9a0289d2b311b150b92c>
Actual :<{timestamp=1553701378, machineIdentifier=9032371, processIdentifier=4529, counter=5290284, timeSecond=1553701378, time=1553701378000, date=1553701378000}>
<Click to see difference>
Any help would be appreciated (including any pointers if you think my general approach could be improved!).
Cheers!
Jackson doesn't know your ObjectId instance should be serialized as 5c9b9a0289d2b311b150b92c and not as:
{
"timestamp": 1553701378,
"machineIdentifier": 9032371,
"processIdentifier": 4529,
"counter": 5290284,
"time": 1553701378000,
"date": 1553701378000,
"timeSecond": 1553701378
}
Luckily it's easy to fix. The ObjectId#toString() method (which will internally invoke ObjectId#toHexString()) allows you to convert the ObjectId instance into a 24-byte hexadecimal string representation.
So you could use #JsonSerialize along with ToStringSerializer to have the ObjectId instance represented as a string:
#JsonSerialize(using = ToStringSerializer.class)
private ObjectId id;
Then, in your test, use the ObjectId#toString() method (or ObjectId#toHexString()) for the assertion:
.andExpect(jsonPath("$.id", is(id.toString())))
Alternatively, assuming that you are using Spring Data for MongoDB, instead of ObjectId, you could use:
#Id
private String id;
You also could handle the conversion of ObjectId to String in your mapper layer.

No procedure/function/signature

I am relatively new at using stored procedures and I have really run up aganst the wall. I am receiving the following error message using the Spring JdbcTemplate. My dev environment is Xubuntu, jdk 1.8.
The stack trace is:
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: Unable to determine the correct call signature - no procedure/function/signature for 'PROCONEINPARAMETER'
at org.springframework.jdbc.core.metadata.GenericCallMetaDataProvider.processProcedureColumns(GenericCallMetaDataProvider.java:347)
at org.springframework.jdbc.core.metadata.GenericCallMetaDataProvider.initializeWithProcedureColumnMetaData(GenericCallMetaDataProvider.java:112)
at org.springframework.jdbc.core.metadata.CallMetaDataProviderFactory$1.processMetaData(CallMetaDataProviderFactory.java:133)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:299)
at org.springframework.jdbc.core.metadata.CallMetaDataProviderFactory.createMetaDataProvider(CallMetaDataProviderFactory.java:73)
at org.springframework.jdbc.core.metadata.CallMetaDataContext.initializeMetaData(CallMetaDataContext.java:286)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.compileInternal(AbstractJdbcCall.java:303)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.compile(AbstractJdbcCall.java:288)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.checkCompiled(AbstractJdbcCall.java:348)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:375)
at org.springframework.jdbc.core.simple.SimpleJdbcCall.executeFunction(SimpleJdbcCall.java:153)
at test.jdbc.StringDao.executeProcOneINParameter(StringDao.java:21)
at test.jdbc.SimpleJdbcTest.main(SimpleJdbcTest.java:15)
Code:
SimpleJdbc.java
package test.jdbc;
import java.util.Map;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SimpleJdbcTest {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
StringDao dao=(StringDao)ctx.getBean("edao");
String request = new String(" Wow, this works!");
String response = dao.executeProcOneINParameter(request);
if (response != null && !response.equals(new String())) {
System.out.println("stored proc worked: "+ response);
} else {
System.err.println("stored proc did not work.");
}
}
}
StringDao.java
package test.jdbc;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
public class StringDao {
private static final String PROC_NAME = "PROCONEINPARAMETER";
private static final String CAT_NAME = "LISTENER";
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public String executeProcOneINParameter(String callParam){
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName(CAT_NAME)
.withProcedureName(PROC_NAME);
return jdbcCall.executeFunction(String.class, callParam);
}
}
Stored Proc:
PROCONEINPARAMETER
CREATE OR REPLACE PROCEDURE procOneINParameter(param1 IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World IN parameter ' || param1);
END;
Aside from the problems that #Alex posted, and I corrected, the final problem was the following:
static final String PROC_NAME = "PROCONEINPARAMETER";
private static final String CAT_NAME = "LISTENER";
…..
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName(CAT_NAME)
.withProcedureName(PROC_NAME);
instead of:
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withSchemaName(CAT_NAME)
.withProcedureName(PROC_NAME);
Obviously, there was no way for anyone to know that I was using catalog and schema name interchangeably.
You are trying to call a procedure, not a function. But you are calling it via the executeFunction() method, and specifying a return type of String.
You need to use execute() instead, still passing the procedure argument, but without the return type (since there isn't one from a procedure):
Map<String,Object> out = jdbcCall.execute(callParam);
Your procedure doesn't have any OUT parameters either so out will be empty.
Had similar problem.
Issue was : Schema Name was in uppercase, so it was taking double quotes.
eg : SchemaName was ABCD, while executing postgres was expecting "ABCD".
Resolution : converted schema name to lowercase.

How to store Java 8 (JSR-310) dates in elasticsearch

I know elasticsearch can only save Date types internally. But can i make it aware to store/convert Java 8 ZonedDateTime, as i use this type in my entity?
I'm using spring-boot:1.3.1 + spring-data-elasticsearch with jackson-datatype-jsr310 on the classpath. No conversions seem to apply neither when i try to save a ZonedDateTime nor Instant or something else.
One way of doing this is to create custom converter like this:
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.ZonedDateTime;
import static java.time.format.DateTimeFormatter.*;
public class ZonedDateTimeConverter implements JsonSerializer<ZonedDateTime>, JsonDeserializer<ZonedDateTime> {
#Override
public ZonedDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
return ZonedDateTime.parse(jsonElement.getAsString(), ISO_DATE_TIME);
}
#Override
public JsonElement serialize(ZonedDateTime zonedDateTime, Type type, JsonSerializationContext jsonSerializationContext) {
return new JsonPrimitive(zonedDateTime.format(ISO_DATE_TIME));
}
}
and then configure JestClientFactory to use this converter:
Gson gson = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeConverter()).create();
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig
.Builder("elastic search URL")
.multiThreaded(true)
.gson(gson)
.build());
client = factory.getObject();
Hope it'll help.

Calling through Spring a procedure with collection of object (oracle ARRAY STRUCT)

im trying to execute a procedure which contains between others a parameter which is a collection of object (oracle). I have managed them lot of times without spring, but I'm a bit lost trying to do it with spring, althoug there is some information on the internet, I can't find a full example in order to compare my code. Spring doc has just fragments. Probably my code is wrong but i ignore why, could you help me? I'm running simplier procedures without problems. My DAO looks like this:
//[EDITED]
private SimpleJdbcCall pActualizaDia;
....
#Autowired
public void setDataSource(DataSource dataSource) {
pActualizaDia = new SimpleJdbcCall(dataSource).withCatalogName("PTR_GRUPOS_TRABAJO").withProcedureName("UPDATE_DIA");
pActualizaDia.getJdbcTemplate().setNativeJdbcExtractor(new OracleJdbc4NativeJdbcExtractor());
}
...
public Calendario updateSingle(final Calendario calendario) {
SqlTypeValue cambiosEmpresa = new AbstractSqlTypeValue() {
protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
ArrayDescriptor arrayDescriptor = new ArrayDescriptor("TTPTR_CAMBIO_EMPRESA", conn);
Object[] collection = new Object[calendario.getCambiosEmpresa().size()];
int i = 0;
for (CeAnoEmp ce : calendario.getCambiosEmpresa()) {
collection[i++] = new STRUCT(new StructDescriptor("TPTR_CAMBIO_EMPRESA", conn), conn, new Object[] {
ce.getSQLParam1(),
//...more parameters here in order to fit your type.
ce.getSQLparamn() });
}
ARRAY idArray = new ARRAY(arrayDescriptor, conn, collection);
return idArray;
}
};
MapSqlParameterSource mapIn = new MapSqlParameterSource();
mapIn.addValue("P_ID_ESCALA", calendario.getEscala().getIdEscala());
//more simple params here
//Here it is the Oracle ARRAY working properly
pActualizaDia.declareParameters(new SqlParameter("P_CAMBIOS_EMPRESA",
OracleTypes.STRUCT, "TTPR_CAMBIO_EMPRESA"));
mapIn.addValue("P_CAMBIOS_EMPRESA",cambiosEmpresa);
//When executing the procedure it just work :)
pActualizaDia.execute(mapIn);
return null;
}
The exception I get sais
java.lang.ClassCastException: $Proxy91 cannot be cast to oracle.jdbc.OracleConnection
I've been reading more about this topic and i found that It almost seems like if using Oracle Arrays you also have to cast the connection to be an oracle connection.
However, most Spring jdbc framework classes like SimpleJDBCTemplate and StoredProcedure hide the connection access from you. Do I need to subclass one of those and override a method somewhere to get the dbcp connection and then cast it to an Oracle connection?
Thank you very much.
I've solved it finally, I've edited the post in order to have an example for anyone looking for a piece of code to solve this issue.
There are two important things to have in mind:
1) It's mandatory to set oracle extractor in jdbctemplate in order to cast properly the connection to get oracle functionality.
2) When using this extractor ojdbc and JRE version must be the same, any other case you'll get an abstractmethodinvocation exception.
Thanks anyone who tried to solve it and hope it helps.
you can use spring to call a procedure with array of collection of oracle structure : below a simple example to do this
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.sql.DataSource;
import oracle.jdbc.driver.OracleConnection;
import oracle.jdbc.driver.OracleTypes;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;
public class SpringObjectMapper {
public static class SaveObjectFunction extends StoredProcedure {
final static Logger logger = LoggerFactory.getLogger(SavePackInterFunction.class);
private static final String PROC_NAME = "schema.proc_name";
private final static String ARRAY_OF_VALUE_PARAM_NAME = "ARRAY_OF_VALUE";
private final static String OUT_PARAM_NAME = "out";
public SaveObjectFunction(DataSource dataSource) {
super(dataSource, PROC_NAME);
declareParameter(new SqlParameter(ARRAY_OF_VALUE_PARAM_NAME, OracleTypes.ARRAY, "schema.array_object_type"));
compile();
}
public String execute(Collection<Model> values) {
logger.info("------------------------EnregInterlocuteurPrcedure::execute : begin----------------------------");
String message = null;
try {
OracleConnection connection = getJdbcTemplate().getDataSource().getConnection().unwrap(OracleConnection.class);
ArrayDescriptor arrayValueDescriptor = new ArrayDescriptor("schema.array_object_type", connection);
StructDescriptor typeObjeDescriptor = new StructDescriptor("schema.object_type", connection);
Object[] valueStructArray = new Object[values.size()];
int i = 0;
for (Iterator<Model> iterator = values.iterator(); iterator.hasNext();) {
Model model = (Model) iterator.next();
STRUCT s = new STRUCT(typeObjeDescriptor, connection, new Object[] {model.getAttribute1(), model.getAttribute2(), model.getAttribute3(),
model.getAttribute4(), model.getAttribute5(), model.getAttribute6(), model.getAttribute7()});
valueStructArray[i++] = s;
}
ARRAY inZoneStructArray = new ARRAY(arrayValueDescriptor, connection, valueStructArray);
Map<String, Object> inputs = new HashMap<String, Object>();
inputs.put(ARRAY_OF_VALUE_PARAM_NAME, inZoneStructArray);
Map<String, Object> out = super.execute(inputs);
message = (String) out.get(OUT_PARAM_NAME);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return message;
}
}
}

JAXB marshal/unmarshal - ing SWT.Image or AWT BufferedImage

I am trying to marshal with jaxb an object which contains an Image, and afterwards unmarshalling it (i.e. save/load).
Is there a way to store that image?
I am trying to create a function which returns the byte array describing the swt.image imagedata, but once I marked it as an #XmlElement, the process of storing it fails throwing an Exception like this:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
JAXB annotation is placed on a method that is not a JAXB property
this problem is related to the following location:
at #javax.xml.bind.annotation.XmlElement()
Also, I have tested to convert the SWT.Image to a AWT.BufferedImage, but I still get the same Exception.
Your exception indicates that you have placed an annotation on a method that isn't an accessor (get/set method). Below is an example using a java.awt.Image property:
Root
package forum9094655;
import java.awt.Image;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Root {
private Image image;
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
}
Demo
package forum9094655;
import java.awt.Image;
import java.awt.image.BufferedImage;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Root root = new Root();
Image image = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB);
root.setImage(image);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<image>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mNgYGAAAAAEAAHI6uv5AAAAAElFTkSuQmCC</image>
</root>

Resources