extension function using saxon s9api - saxon

I am trying to add an extension function, but is failing with :
Caused by: net.sf.saxon.trans.XPathException: Unknown system function follow()
at net.sf.saxon.expr.parser.XPathParser.grumble(XPathParser.java:282)
I see (in debug) that function registered with the integrated library. I was expecting saxon to look for the function in the integrated library but it is searching in system functions and throwing error. What is causing this function to be represented as a system function.
I am using the following :
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId>
<version>9.7.0-14</version>
</dependency>
Thank you
my code is
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.ExtensionFunctionCall;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.XPathCompiler;
import net.sf.saxon.s9api.XPathExecutable;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;
public class FollowTest {
public static void main(String[] args) throws Exception {
new FollowTest().test();
}
private void test () throws Exception {
Processor proc = new Processor(false);
proc.registerExtensionFunction(new Follow());
XPathCompiler xx = proc.newXPathCompiler();
XPathExecutable x = xx.compile("follow(/a/b/c)/type='xyz'");
}
public class Follow extends ExtensionFunctionDefinition {
#Override
public StructuredQName getFunctionQName() {
return new StructuredQName("", "http://example.com/saxon-extension", "follow");
}
#Override
public int getMinimumNumberOfArguments() {
return 1;
}
#Override
public int getMaximumNumberOfArguments() {
return 1;
}
#Override
public SequenceType[] getArgumentTypes() {
return new net.sf.saxon.value.SequenceType[] {SequenceType.SINGLE_STRING,};
}
#Override
public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
return SequenceType.NODE_SEQUENCE;
}
#Override
public boolean trustResultType() {
return true;
}
#Override
public boolean dependsOnFocus() {
return false;
}
#Override
public boolean hasSideEffects() {
return false;
}
#Override
public ExtensionFunctionCall makeCallExpression() {
return null;
}
private class followCall extends ExtensionFunctionCall {
#Override
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
return null;
}
}
}
}

In the XPath expression you have written
follow(/a/b/c)
A function name with no namespace prefix is assumed to be in the default namespace for functions, which by default is the system function namespace http://www.w3.org/2005/xpath-functions. You need to use a prefix that's bound to the URI appearing in the extension function definition, namely http://example.com/saxon-extension

Related

Weld SE: not injecting inner dependency in Junit Test

I am using Weld SE in a junit test. It seems it does not inject an inner field of a CDI bean. I am using the maven artifcat weld-se-shaded (4.0.2-Final)
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class XService {
#Override
public String toString() {
return "hi from XService";
}
}
// ---
import javax.enterprise.context.ApplicationScoped;
#ApplicationScoped
public class YService {
#Override
public String toString() {
return "hi from YService";
}
}
// ---
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class ZService {
#Inject
public YService yService;
#Override
public String toString() {
return "hi from ZService";
}
}
// ---
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class WeldTest {
private WeldContainer container;
#Before
public void startContainer() {
Weld weld = new Weld();
weld.disableDiscovery();
weld.addBeanClasses(XService.class, YService.class, ZService.class);
container = weld.initialize();
}
#After
public void stopContainer() {
container.shutdown();
}
#Test
public void shouldCreateXServiceInstance() {
// ok
XService xService = container.select(XService.class).get();
assertThat(xService.toString()).isEqualTo("hi from XService");
}
#Test
public void shouldCreateYServiceInstance() {
// ok
YService yService = container.select(YService.class).get();
assertThat(yService.toString()).isEqualTo("hi from YService");
}
#Test
public void shouldInjectYServiceInZService() {
// fails
ZService zService = container.select(ZService.class).get();
assertThat(zService.toString()).isEqualTo("hi from ZService");
// yService is null, assertion fails
assertThat(zService.yService).isNotNull();
}
}
There is no exception, the field is just null. Instead of field injection I tried constructor injection:
#ApplicationScoped
public class ZService {
public YService yService;
#Inject
public ZService(YService yService) {
this.yService = yService;
}
#Override
public String toString() {
return "hi from ZService";
}
}
In that case I get an exception message: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type ZService with qualifiers
Seems that Weld 4 only considers jakarta.* imports. If I change javax.* imports to jakarta.* the example works. It also works if I am downgrading to Weld 3 with javax.* imports.

EventBus in Reactor 3.x

I know that EventBus is deprecated in Reactor3.x, and the suggested solution is ReplayProcessor. I have read https://github.com/reactor/reactor-core/issues/375. But the code here is too draft. I created a demo project to prove the idea here. Can someone give some comments?
======== Application.java
package hello;
import org.reactivestreams.Subscription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Flux;
import reactor.core.publisher.ReplayProcessor;
import reactor.core.publisher.BaseSubscriber;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application implements CommandLineRunner {
private static final int NUMBER_OF_QUOTES = 10;
#Bean
ReplayProcessor createReplayProcessor() {
ReplayProcessor<MyEvent> rp = ReplayProcessor.create();
Flux<MyEvent> interest1 = rp.filter(ev -> filterInterest1(ev));
Flux<MyEvent> interest2 = rp.filter(ev -> filterInterest2(ev));
interest1.subscribe(new BaseSubscriber<MyEvent>() {
#Override
protected void hookOnSubscribe(Subscription subscription) {
requestUnbounded();
}
#Override
protected void hookOnNext(MyEvent value) {
//todo: call service method
System.out.println("event 1 handler -> event name:" + value.getEventName());
}
});
interest2.subscribe(new BaseSubscriber<MyEvent>() {
#Override
protected void hookOnSubscribe(Subscription subscription) {
requestUnbounded();
}
#Override
protected void hookOnNext(MyEvent value) {
//todo: call service method
System.out.println("event2 handler -> event name:" + value.getEventName());
}
});
return rp;
}
public boolean filterInterest1(MyEvent myEvent) {
if (myEvent != null && myEvent.getEventName() != null
&& myEvent.getEventName().equalsIgnoreCase("event1")) {
return true;
}
return false;
}
public boolean filterInterest2(MyEvent myEvent) {
if (myEvent != null && myEvent.getEventName() != null
&& myEvent.getEventName().equalsIgnoreCase("event2")) {
return true;
}
return false;
}
#Autowired
private Publisher publisher;
#Bean
public CountDownLatch latch() {
return new CountDownLatch(NUMBER_OF_QUOTES);
}
#Override
public void run(String... args) throws Exception {
publisher.publishQuotes(NUMBER_OF_QUOTES);
}
public static void main(String[] args) throws InterruptedException {
ApplicationContext app = SpringApplication.run(Application.class, args);
app.getBean(CountDownLatch.class).await(10, TimeUnit.SECONDS);
}
}
==========MyEvent.java=============
package hello;
public class MyEvent {
private String eventName = "";
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public MyEvent(String eventName) {
this.eventName = eventName;
}
public void filterInterest1(MyEvent myEvent) {
}
}
=============Publisher.java ===========
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.ReplayProcessor;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
#Service
public class Publisher {
#Autowired
ReplayProcessor rp;
#Autowired
CountDownLatch latch;
public void publishQuotes(int numberOfQuotes) throws InterruptedException {
long start = System.currentTimeMillis();
rp.onNext(new MyEvent("event1"));
rp.onNext(new MyEvent("event2"));
rp.onNext(new MyEvent("event3"));
long elapsed = System.currentTimeMillis() - start;
System.out.println("Elapsed time: " + elapsed + "ms");
System.out.println("Average time per quote: " + elapsed / numberOfQuotes + "ms");
}
}
The whole code is https://github.com/yigubigu/reactor-start-sample.git
IMHO you can relay in Spring event handlers. Matt Raible and Josh Long use that in this couple of tutorials:
https://developer.okta.com/blog/2018/09/24/reactive-apis-with-spring-webflux
https://developer.okta.com/blog/2018/09/25/spring-webflux-websockets-react
Key takeaways:
#Component
class ProfileCreatedEventPublisher implements
ApplicationListener<ProfileCreatedEvent>,
Consumer<FluxSink<ProfileCreatedEvent>>
Uses an event loop to take events from a LinkedBlockingQueue.
#Override
public void onApplicationEvent(ProfileCreatedEvent event)
Queue the events that can be published anywhere within your app.
ProfileCreatedEventPublisher is used in ServerSentEventController to create a Flux of events (that can be chained with a filter), it transforms and sends them to a web client.

Google Dataflow: java.lang.IllegalArgumentException: Cannot setCoder(null)

I am trying to build a custom sink for unzipping files.
Having this simple code:
public static class ZipIO{
public static class Sink extends com.google.cloud.dataflow.sdk.io.Sink<String> {
private static final long serialVersionUID = -7414200726778377175L;
private final String unzipTarget;
public Sink withDestinationPath(String s){
if(s!=""){
return new Sink(s);
}
else {
throw new IllegalArgumentException("must assign destination path");
}
}
protected Sink(String path){
this.unzipTarget = path;
}
#Override
public void validate(PipelineOptions po){
if(unzipTarget==null){
throw new RuntimeException();
}
}
#Override
public ZipFileWriteOperation createWriteOperation(PipelineOptions po){
return new ZipFileWriteOperation(this);
}
}
private static class ZipFileWriteOperation extends WriteOperation<String, UnzipResult>{
private static final long serialVersionUID = 7976541367499831605L;
private final ZipIO.Sink sink;
public ZipFileWriteOperation(ZipIO.Sink sink){
this.sink = sink;
}
#Override
public void initialize(PipelineOptions po) throws Exception{
}
#Override
public void finalize(Iterable<UnzipResult> writerResults, PipelineOptions po) throws Exception {
long totalFiles = 0;
for(UnzipResult r:writerResults){
totalFiles +=r.filesUnziped;
}
LOG.info("Unzipped {} Files",totalFiles);
}
#Override
public ZipIO.Sink getSink(){
return sink;
}
#Override
public ZipWriter createWriter(PipelineOptions po) throws Exception{
return new ZipWriter(this);
}
}
private static class ZipWriter extends Writer<String, UnzipResult>{
private final ZipFileWriteOperation writeOp;
public long totalUnzipped = 0;
ZipWriter(ZipFileWriteOperation writeOp){
this.writeOp = writeOp;
}
#Override
public void open(String uID) throws Exception{
}
#Override
public void write(String p){
System.out.println(p);
}
#Override
public UnzipResult close() throws Exception{
return new UnzipResult(this.totalUnzipped);
}
#Override
public ZipFileWriteOperation getWriteOperation(){
return writeOp;
}
}
private static class UnzipResult implements Serializable{
private static final long serialVersionUID = -8504626439217544799L;
public long filesUnziped=0;
public UnzipResult(long filesUnziped){
this.filesUnziped=filesUnziped;
}
}
}
}
The processing fails with error:
Exception in thread "main" java.lang.IllegalArgumentException: Cannot setCoder(null)
at com.google.cloud.dataflow.sdk.values.TypedPValue.setCoder(TypedPValue.java:67)
at com.google.cloud.dataflow.sdk.values.PCollection.setCoder(PCollection.java:150)
at com.google.cloud.dataflow.sdk.io.Write$Bound.createWrite(Write.java:380)
at com.google.cloud.dataflow.sdk.io.Write$Bound.apply(Write.java:112)
at com.google.cloud.dataflow.sdk.runners.DataflowPipelineRunner$BatchWrite.apply(DataflowPipelineRunner.java:2118)
at com.google.cloud.dataflow.sdk.runners.DataflowPipelineRunner$BatchWrite.apply(DataflowPipelineRunner.java:2099)
at com.google.cloud.dataflow.sdk.runners.PipelineRunner.apply(PipelineRunner.java:75)
at com.google.cloud.dataflow.sdk.runners.DataflowPipelineRunner.apply(DataflowPipelineRunner.java:465)
at com.google.cloud.dataflow.sdk.runners.BlockingDataflowPipelineRunner.apply(BlockingDataflowPipelineRunner.java:169)
at com.google.cloud.dataflow.sdk.Pipeline.applyInternal(Pipeline.java:368)
at com.google.cloud.dataflow.sdk.Pipeline.applyTransform(Pipeline.java:275)
at com.google.cloud.dataflow.sdk.runners.DataflowPipelineRunner.apply(DataflowPipelineRunner.java:463)
at com.google.cloud.dataflow.sdk.runners.BlockingDataflowPipelineRunner.apply(BlockingDataflowPipelineRunner.java:169)
at com.google.cloud.dataflow.sdk.Pipeline.applyInternal(Pipeline.java:368)
at com.google.cloud.dataflow.sdk.Pipeline.applyTransform(Pipeline.java:291)
at com.google.cloud.dataflow.sdk.values.PCollection.apply(PCollection.java:174)
at com.mcd.de.tlogdataflow.StarterPipeline.main(StarterPipeline.java:93)
Any help is appreciated.
Thanks & BR
Philipp
This crash is caused by a bug in the Dataflow Java SDK (specifically, this line) which was also present in the Apache Beam (incubating) Java SDK.
The method Sink.WriterOperation#getWriterResultCoder() must always be overridden, but we failed to mark it abstract. It is fixed in Beam, but unchanged in the Dataflow SDK. You should override this method and return an appropriate coder.
You have some options to come up with the coder:
Write your own small coder class, wrapping one of VarLongCoder or BigEndianLongCoder
Just use a long instead of the UnzipResult structure so you can use those as-is.
Less advisable due to the excess size, you could use SerializableCoder.of(UnzipResult.class)

Jersy2 inject slf4j Logger

I'm trying to understand Jersey 2 development and context-dependency injection.
I don't understand how to inject into a resource an object that needs initialization parameters in the constructor.
For example: I'd like to #Inject slf4j Logger, built using LoggerFactory.
My resource class is:
#Path("/myresource")
public class MyResource {
#Inject
private Logger log;
#GET
#Produces(MediaType.APPLICATION_JSON)
public Answer status() {
log.info("STATUS");
return new Answer(200, "Server up and running # "+ ZonedDateTime.now());
}
}
My Resource config is:
public class MyAppextends ResourceConfig {
public MyApp() {
register(new MyBinder());
packages(true, "my.packages");
}
}
public class MyBinder extends AbstractBinder {
#Override
protected void configure() {
bindFactory(MyLoggerFactory.class).to(org.slf4j.Logger.class);
}
}
Finally, the Factory is:
public class MyLoggerFactory implements Factory<Logger> {
#Override
public Logger provide() {
return LoggerFactory.getLogger(TYPE_FOR_LOGGING.class);
}
#Override
public void dispose(Logger logger) {
}
}
How can I specify TYPE_FOR_LOGGING as argument, in order to Inject the correctly initialized Logger in every resource I want?
Thanks
What you are looking for is called the InstantiationService. You can inject it into Factories to find out who is calling the factory inside of the provide method.
Below find a code sample from the hk2 tests that illustrate the use of the InstantiationService.
#Singleton
public class CorrelationFactory implements Factory<PerLookupServiceWithName> {
private final static PerLookupServiceWithName NULL_SERVICE = new PerLookupServiceWithName() {
#Override
public String getName() {
return null;
}
};
#Inject
private InstantiationService instantiationService;
/* (non-Javadoc)
* #see org.glassfish.hk2.api.Factory#provide()
*/
#Override #PerLookup
public PerLookupServiceWithName provide() {
InstantiationData data = instantiationService.getInstantiationData();
if (data == null) {
return NULL_SERVICE;
}
Injectee parent = data.getParentInjectee();
if (parent == null) {
return NULL_SERVICE;
}
Class<?> parentClass = parent.getInjecteeClass();
if (parentClass == null) {
return NULL_SERVICE;
}
Correlator correlator = parentClass.getAnnotation(Correlator.class);
if (correlator == null) {
return NULL_SERVICE;
}
final String fName = correlator.value();
return new PerLookupServiceWithName() {
#Override
public String getName() {
return fName;
}
};
}
/* (non-Javadoc)
* #see org.glassfish.hk2.api.Factory#dispose(java.lang.Object)
*/
#Override
public void dispose(PerLookupServiceWithName instance) {
// DO nothing
}
}

Jedis Cache implementation without JedisPool/commons-pool2-2.0

How to implement Jedis without JedisPool/commons-pool2-2.0 because still we are using jdk 1.5(commons-pool2-2.0 does not support JDK 1.5)
How to implement a thread-safe connection pooling?
I'm not sure about Jedis compatibility with Java 5. You can create your own pooling based on the older commons-pool 1.6 library. You do not need to have commons-pool2 on your class path to run jedis. I used Jedis 2.7.3 and commons-pool 1.6 to validate the solution approach.
Find the example code attached:
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import redis.clients.jedis.Jedis;
public class JedisWithOwnPooling {
public static void main(String[] args) throws Exception {
ObjectPool<Jedis> pool = new GenericObjectPool(new JedisFactory("localhost"));
Jedis j = pool.borrowObject();
System.out.println(j.ping());
pool.returnObject(j);
pool.close();
}
private static class JedisFactory implements PoolableObjectFactory<Jedis> {
private String host;
/**
* Add fields as you need. That's only an example.
*/
public JedisFactory(String host) {
this.host = host;
}
#Override
public Jedis makeObject() throws Exception {
return new Jedis(host);
}
#Override
public void destroyObject(Jedis jedis) throws Exception {
jedis.close();
}
#Override
public boolean validateObject(Jedis jedis) {
return jedis.isConnected();
}
#Override
public void activateObject(Jedis jedis) throws Exception {
if (!jedis.isConnected()) {
jedis.connect();
}
}
#Override
public void passivateObject(Jedis jedis) throws Exception {
}
}
}

Resources