Dynamic Method Invocation and JAXBElement Type on CXF - apache

I wrote the small application below to list all the methods and of a soap service using Apache CXF library. This application lists all the methods of the service, but as it is seen on the output when you run this application, input parameters and return types of the service methods are JAXBElement for the complex types. I want cxf not to generate JAXBElement, instead I want the complex types in their original classes generated on runtime. As it is said on http://s141.codeinspot.com/q/1455881 , it can be done by setting generateElementProperty property's value to false for wsdl2java utility of cxf library, but I couldn't find the same parameter for dynamic method invocation with cxf library. I want to obtain input parameters and return types in their original types.
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.List;
import org.apache.cxf.binding.Binding;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.service.model.BindingInfo;
import org.apache.cxf.service.model.BindingMessageInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.MessagePartInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.service.model.ServiceModelUtil;
public class Main {
public static void main(String[] args) {
URL wsdlURL = null;
try {
wsdlURL = new URL("http://path_to_wsdl?wsdl");
} catch (MalformedURLException e) {
e.printStackTrace();
}
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient(wsdlURL, classLoader);
Binding binding = client.getEndpoint().getBinding();
BindingInfo bindingInfo = binding.getBindingInfo();
Collection<BindingOperationInfo> operations = bindingInfo.getOperations();
for(BindingOperationInfo boi:operations){
OperationInfo oi = boi.getOperationInfo();
BindingMessageInfo inputMessageInfo = boi.getInput();
List<MessagePartInfo> parts = inputMessageInfo.getMessageParts();
System.out.println("function name: "+oi.getName().getLocalPart());
List<String> inputParams = ServiceModelUtil.getOperationInputPartNames(oi);
System.out.println("input parameters: "+inputParams);
for(MessagePartInfo partInfo:parts){
Class<?> partClass = partInfo.getTypeClass(); //here we have input parameter object on each iteration
Method[] methods = partClass.getMethods();
for(Method method:methods){
System.out.println("method: "+method);
Class<?>[] paramTypes = method.getParameterTypes();
for(Class paramType:paramTypes){
System.out.println("param: "+paramType.getCanonicalName());
}
Class returnType = method.getReturnType();
System.out.println("returns: "+returnType.getCanonicalName());
}
System.out.println("partclass: "+partClass.getCanonicalName());
}
}
System.out.println("binding: " + binding);
}
}

Create a binding file that looks like:
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateElementProperty="false">
<xjc:simple />
</jaxb:globalBindings>
</jaxb:bindings>
and pass that into the JaxWsDynamicClientFactory via the createClient method that takes the List of binding files.

Related

xd.lck lock file is not removed after store is closed

My assumption on xodus database locking was that closing the entity store would close the database.
I implemented this with a simple example using the use pattern that calls close:
package whatever
import jetbrains.exodus.entitystore.Entity
import kotlinx.dnq.XdEntity
import kotlinx.dnq.XdModel
import kotlinx.dnq.XdNaturalEntityType
import kotlinx.dnq.store.container.StaticStoreContainer
import kotlinx.dnq.util.initMetaData
import kotlinx.dnq.xdRequiredStringProp
import org.junit.Test
import java.nio.file.Files
class UnclosedTest {
private val dbFolder = Files.createTempDirectory(null).toFile()
private val store = StaticStoreContainer.init(
dbFolder = dbFolder,
environmentName = "store"
).also {
XdModel.registerNodes(
Bogus
)
initMetaData(XdModel.hierarchy, it)
}
#Test
fun `lock file is removed when store is closed`() {
store.use { store ->
store.transactional {
Bogus.new {
text = "gnarf"
}
}
}
assert(dbFolder.exists())
assert(dbFolder.isDirectory)
assert(!dbFolder.resolve("xd.lck").exists())
}
class Bogus(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Bogus>()
var text by xdRequiredStringProp()
}
}
Surprisingly, this test fails with the xd.lck file still being present.
How do I close all resources, making sure the lockfile is removed?
The xd.lck file is being released on closing the database, not removed, regardless of which API do you use: Environments, EntityStores, or Xodus-DNQ DSL. See how it is implemented.

How to test Apache HttpClient RequestConfig values are set correctly? No public getters present

I have this class to configure a HttpClient instance:
package com.company.fraud.preauth.service.feignaccertifyclient;
import com.company.fraud.preauth.config.ProviderClientConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
#Slf4j
#Configuration
#RequiredArgsConstructor
public class FeignClientConfig {
private final ProviderClientConfig providerClientConfig;
public HttpClient buildHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
RequestConfig.Builder requestBuilder = RequestConfig.custom();
requestBuilder.setConnectTimeout(providerClientConfig.getConnectionTimeout());
requestBuilder.setConnectionRequestTimeout(providerClientConfig.getConnectionRequestTimeout());
requestBuilder.setSocketTimeout(providerClientConfig.getSocketTimeout());
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
return HttpClientBuilder.create()
.setMaxConnPerRoute(providerClientConfig.getMaxConnectionNumber())
.setDefaultRequestConfig(requestBuilder.build())
.setSSLContext(builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()).build())
.build();
}
}
How to unit test this class, to see into the resulted HttpClient that these values are correctly set?
From the httpClient I cannot get access to its RequestConfig.
I am aware of these two posts:
How do I test a private function or a class that has private methods, fields or inner classes?
(the number of upvotes in this question shows that it is a concurrent and controversial topic in testing, and my situation may offer an example that why we should look into the inner state of an instance in testing, despite that it is private)
Unit test timeouts in Apache HttpClient
(it shows a way of adding an interceptor in code to check configure values, but I don't like it because I want to separate tests with functional codes)
Is there any way? I understand that this class should be tested, right? You cannot blindly trust it to work; and checking it "notNull" seems fragile to me.
This link may point me to the right direction:
https://dzone.com/articles/testing-objects-internal-state
It uses PowerMock.Whitebox to check internal state of an instance.
So I have checked into PowerMock.Whitebox source code, and it turns out reflection is used internally. And, as PowerMock is said to be not compatible with JUnit 5 yet(till now), and I don't want to add another dependency just for testing, so I will test with reflection.
package com.company.fraud.preauth.service.feignaccertifyclient;
import com.company.fraud.preauth.config.PreAuthConfiguration;
import com.company.fraud.preauth.config.ProviderClientConfig;
import com.company.fraud.preauth.config.StopConfiguration;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.lang.reflect.Field;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {
PreAuthConfiguration.class,
StopConfiguration.class,
})
public class FeignClientConfigTest {
#Mock
private ProviderClientConfig providerClientConfig;
#Test
#DisplayName("should return HttpClient with defaultConfig field filled with values in providerClientConfig")
public void shouldReturnHttpClientWithConfiguredValues() throws Exception {
// given
when(providerClientConfig.getConnectionRequestTimeout()).thenReturn(30000);
when(providerClientConfig.getConnectionTimeout()).thenReturn(30);
when(providerClientConfig.getMaxConnNumPerRoute()).thenReturn(20);
when(providerClientConfig.getSocketTimeout()).thenReturn(10);
FeignClientConfig feignClientConfig = new FeignClientConfig(providerClientConfig);
// when
HttpClient httpClient = feignClientConfig.buildHttpClient();
// then
// I want to test internal state of built HttpClient and this should be checked
// I tried to use PowerMock.Whitebox, but then I found it uses reflection internally
// I don't want to introduce another dependency, and PowerMock is said not to be compatible with JUnit 5, so..
Field requestConfigField = httpClient.getClass().getDeclaredField("defaultConfig");
requestConfigField.setAccessible(true);
RequestConfig requestConfig = (RequestConfig)requestConfigField.get(httpClient);
assertThat(requestConfig.getConnectionRequestTimeout(), equalTo(30000));
assertThat(requestConfig.getConnectTimeout(), equalTo(30));
assertThat(requestConfig.getSocketTimeout(), equalTo(10));
}
}
Also, I answer the first question in OP about when to test private members in a class here
Whitebox was working for me. As it is not documented here I'm adding my version:
in my case wanted to test that the timeout is different from 0 to avoid deadlock
HttpClient httpClient = factory.getHttpClient();
RequestConfig sut = Whitebox.getInternalState(httpClient, "defaultConfig");
assertNotEquals(0, sut.getConnectionRequestTimeout());
assertNotEquals(0, sut.getConnectTimeout());
assertNotEquals(0, sut.getSocketTimeout());

Create data property XSD:string with Jena

the problem sounds so simple: I would like to create an data property for an individual as XSD:string in my ontology.
I can create properties of XSD:DateTime, XSD:Float or XSD:int, but if I use XSD:string, I get a untyped property!
I created a minimal example, which create an ontology with one class, one individual an two data properties. A DateTime, which works like expected and one string, which has no type in the ontology.
I tried with Jena versions 3.4 and 3.0.1 and have no idea who to fix it.
package dataproperty;
import java.io.FileOutputStream;
import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
public class DataProperty {
public static void main(String[] args) throws Exception {
OntModel model = ModelFactory.createOntologyModel();
String OWLPath = "DataProp.owl";
try{
String NS = "http://www.example.org/ontology.owl#";
//Create Ontology
model.createClass(NS+"Test");
Resource r = model.createResource(NS+"Test");
model.createIndividual(NS+"Indi1", r);
r = model.createResource(NS+"Indi1");
model.createDatatypeProperty(NS+"Name");
model.createDatatypeProperty(NS+"Date");
//Add Data Properties
Property p = model.getProperty(NS+"Name");
model.add(r, p, ResourceFactory.createTypedLiteral("MyName", XSDDatatype.XSDstring));
p = model.getProperty(NS+"Date");
model.add(r, p, ResourceFactory.createTypedLiteral("2017-08-12T09:03:40", XSDDatatype.XSDdateTime));
//Store the ontology
FileOutputStream output = null;
output = new FileOutputStream(OWLPath);
model.write(output);
}catch (Exception e) {
System.out.println("Error occured: " + e);
throw new Exception(e.getMessage());
}
}
}
It is not untyped in RDF 1.1 - it's written in short form (better compatibility).
e.g.
https://www.w3.org/TR/turtle/
Section 2.5.1
"If there is no datatype IRI and no language tag, the datatype is xsd:string."

How to delete object in Apache-Cayenne?

My back-end application gets json object via REST API, which exists in database but not exist in Caeynne ObjectContext, how to remove object by id via ObjectContext.
// <dependency>
// <groupId>org.apache.cayenne</groupId>
// <artifactId>cayenne-server</artifactId>
// <version>4.0.M5</version>
// </dependency>
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.configuration.server.ServerRuntime;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.cayenne.test.model.Artist;
#RestController
#RequestMapping(value = "/rest")
public class ArtistRestController {
#DeleteMapping(value = "/artist")
public ResponseEntity deleteArtist(#RequestBody Artist artist) {
ServerRuntime runtime = ServerRuntime
.builder()
.addConfig("cayenne-cayenne_test.xml")
.build();
ObjectContext context = runtime.newContext();
// don't work
context.deleteObject(artist);
context.commitChanges();
return new ResponseEntity<>(HttpStatus.OK);
}
}
If you object have all it's properties and ObjectId properly set you can do something like this:
context.localObject(myObject);
context.deleteObject(myObject);
context.commitChanges();
If you have only raw id you should create object first:
MyObject myObject = Cayenne.objectForPk(context, MyObject.class, id);
context.deleteObject(myObject);
context.commitChanges();
In this case you object probably will be fetched from the database, to restore actual state of it and to track all relationships that can be deleted along with this object.

How do I create a custom directive for Apache Velocity

I am using Apache's Velocity templating engine, and I would like to create a custom Directive. That is, I want to be able to write "#doMyThing()" and have it invoke some java code I wrote in order to generate the text.
I know that I can register a custom directive by adding a line
userdirective=my.package.here.MyDirectiveName
to my velocity.properties file. And I know that I can write such a class by extending the Directive class. What I don't know is how to extend the Directive class -- some sort of documentation for the author of a new Directive. For instance I'd like to know if my getType() method return "BLOCK" or "LINE" and I'd like to know what should my setLocation() method should do?
Is there any documentation out there that is better than just "Use the source, Luke"?
On the Velocity wiki, there's a presentation and sample code from a talk I gave called "Hacking Velocity". It includes an example of a custom directive.
Also was trying to come up with a custom directive. Couldn't find any documentation at all, so I looked at some user created directives: IfNullDirective (nice and easy one), MergeDirective as well as velocity build-in directives.
Here is my simple block directive that returns compressed content (complete project with some directive installation instructions is located here):
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.log.Log;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
/**
* Velocity directive that compresses an HTML content within #compressHtml ... #end block.
*/
public class HtmlCompressorDirective extends Directive {
private static final HtmlCompressor htmlCompressor = new HtmlCompressor();
private Log log;
public String getName() {
return "compressHtml";
}
public int getType() {
return BLOCK;
}
#Override
public void init(RuntimeServices rs, InternalContextAdapter context, Node node) throws TemplateInitException {
super.init(rs, context, node);
log = rs.getLog();
//set compressor properties
htmlCompressor.setEnabled(rs.getBoolean("userdirective.compressHtml.enabled", true));
htmlCompressor.setRemoveComments(rs.getBoolean("userdirective.compressHtml.removeComments", true));
}
public boolean render(InternalContextAdapter context, Writer writer, Node node)
throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
//render content to a variable
StringWriter content = new StringWriter();
node.jjtGetChild(0).render(context, content);
//compress
try {
writer.write(htmlCompressor.compress(content.toString()));
} catch (Exception e) {
writer.write(content.toString());
String msg = "Failed to compress content: "+content.toString();
log.error(msg, e);
throw new RuntimeException(msg, e);
}
return true;
}
}
Block directives always accept a body and must end with #end when used in a template. e.g. #foreach( $i in $foo ) this has a body! #end
Line directives do not have a body or an #end. e.g. #parse( 'foo.vtl' )
You don't need to both with setLocation() at all. The parser uses that.
Any other specifics i can help with?
Also, have you considered using a "tool" approach? Even if you don't use VelocityTools to automatically make your tool available and whatnot, you can just create a tool class that does what you want, put it in the context and either have a method you call to generate content or else just have its toString() method generate the content. e.g. $tool.doMyThing() or just $myThing
Directives are best for when you need to mess with Velocity internals (access to InternalContextAdapter or actual Nodes).
Prior to velocity v1.6 I had a #blockset($v)#end directive to be able to deal with a multiline #set($v) but this function is now handled by the #define directive.
Custom block directives are a pain with modern IDEs because they don't parse the structure correctly, assuming your #end associated with #userBlockDirective is an extra and paints the whole file RED. They should be avoided if possible.
I copied something similar from the velocity source code and created a "blockset" (multiline) directive.
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.TemplateInitException;
import java.io.Writer;
import java.io.IOException;
import java.io.StringWriter;
public class BlockSetDirective extends Directive {
private String blockKey;
/**
* Return name of this directive.
*/
public String getName() {
return "blockset";
}
/**
* Return type of this directive.
*/
public int getType() {
return BLOCK;
}
/**
* simple init - get the blockKey
*/
public void init( RuntimeServices rs, InternalContextAdapter context,
Node node )
throws TemplateInitException {
super.init( rs, context, node );
/*
* first token is the name of the block. I don't even check the format,
* just assume it looks like this: $block_name. Should check if it has
* a '$' or not like macros.
*/
blockKey = node.jjtGetChild( 0 ).getFirstToken().image.substring( 1 );
}
/**
* Renders node to internal string writer and stores in the context at the
* specified context variable
*/
public boolean render( InternalContextAdapter context, Writer writer,
Node node )
throws IOException, MethodInvocationException,
ResourceNotFoundException, ParseErrorException {
StringWriter sw = new StringWriter(256);
boolean b = node.jjtGetChild( 1 ).render( context, sw );
context.put( blockKey, sw.toString() );
return b;
}
}