WildFly naming subsystem: how to bind to a java.util.Properties object - wildfly

I intend to define a JNDI propery of the type java.util.Properties in the WildFly application server to read it from my application.
As described in the an older WildFly documentation one can create a global binding of the type object-factory. In the example is an optional environment tag to hold multiple key/value pairs. That would map exactly my desire to get a java.util.Properties when reading a JNDI resource.
The question is weather there is already an implementiation of javax.naming.spi.ObjectFactory to create a java.util.Properties object out of an object-factory binding or do I need to implement it myself and install it as a separate module (like it is described at mastertheboss.com/...)?

Ok, I just implemented it mysef.
package com.myorg.wildfly.objectfactory;
...
public class WildFlyPropertiesObjectFactory implements ObjectFactory
{
#Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception
{
Properties p = new Properties();
if(environment != null)
{
Set<?> keySet = environment.keySet();
for(Object key : keySet)
{
p.put(key, environment.get(key));
}
}
return p;
}
}
Clean&Build this single class into a JAR file wildfly-properties-objetfactory.jar
Add a module via jboss-cli.sh
module add --name=my.jndi.propertyreader --resource=wildfly-properties-objetfactory.jar --dependencies=javax.api
Create a naming binding via jboss-cli.sh
/subsystem=nameing/binding=java\:\/my_super_cool_jndi_name:add(binding-type=object-factory, module=my.jndi.propertyreader, class=com.myorg.wildfly.objectfactory.WildFlyPropertiesObjectFactory, environment=[key1=value1, key2=value2])
And in my application I can access it in an CDI bean via
public void test() {
Properties p = (Properties) new InitialContext().lookup("java:/my_super_cool_jndi_name");
System.out.printf("Properties: %s%n", p);
}
Or as shown in the mentioned link inject it as a direct dependency #Resource(lookup = "java:/my_super_cool_jndi_name") Properties p;
Works as a charm.

Related

Extend ProposalProvider in external Eclipse Project via Extension Point

I try to extend my MyDSLProposalProvider from an external Eclipse RCP Project. I created an extension point schema which requires a class property which extends my ProposalProvider. In the new project I extend the class an overrode some methods justs to give me some output so I can see that the external method is called. But this is currently not happening. Is there anything I have to consider?
Currently the hirachy looks like:
MyDSLProposalProvider extends AbstractMyDSLProposalProvider
ExternalProposalProvider extends MyDSLProposalProvider
I rewrote a Method generated in the AbstractMyDSLProposalProvider but when its triggered the predefined Method in the AbstractMyDSLProposalProvider is called and not my new implementation.
public class ExternalMyDSLProposalPovider extends MyDSLProposalProvider
{
#Override
public void completeComponent_Name(EObject model, Assignment
assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
System.err.println("extern");
if(model instanceof Component)
{
createProposal("foo", "foo", context, acceptor);
}
super.completeComponent_Name(model, assignment, context, acceptor);
}
}
This is the class in the external Eclipse Project.
Thanks for the help.
When you declare an extension point using a schema that you have defined Eclipse puts that declaration in the extension point registry. That is all that is does, you must then write code to make uses of those declarations.
You read the extension point registry using something like:
IExtensionRegistry extRegistry = Platform.getExtensionRegistry();
IExtensionPoint extPoint = extRegistry.getExtensionPoint("your extension point id");
IConfigurationElement [] elements = extPoint.getConfigurationElements();
elements is now an array of the declarations in the various plugins using the extension point.
IConfigurationElement has various methods to get the values of the attributes of the declaration.
If you have defined a class in one of the attributes you can create an instance of the class using:
IConfigurationElement element = .... a config element
Object obj = element.createExecutableExtension("attribute name");
In your case the result should be your ExternalMyDSLProposalPovider.
You will then need to hook this object up with whatever is doing to proposals.

Neo4j 3.0.3 Stored procedures in Scala

Is there any sample Scala code available for creating stored procedures in Neo4j-3.0.3 ?
I have been trying to create one simple Scala based stored procedure. Below is the Error message I get when I copy my scala-jar file to the neo4j-plugins directory and start the neo4j server :
=================
Caused by: org.neo4j.kernel.lifecycle.LifecycleException: Component 'org.neo4j.kernel.impl.proc.Procedures#1ac0223' was successfully initialized, but failed to start. Please see attached cause exception.
at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.start(LifeSupport.java:444)
at org.neo4j.kernel.lifecycle.LifeSupport.start(LifeSupport.java:107)
at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.newFacade(GraphDatabaseFacadeFactory.java:140)
... 10 more
Caused by: org.neo4j.kernel.api.exceptions.ProcedureException: Unable to find a usable public no-argument constructor in the class `neoscala`. Please add a valid, public constructor, recompile the class and try again.
=================
The scala class that I have used is :
package neoproc
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.procedure.Procedure;
import javax.ws.rs.core.{Context, Response}
class neoscala(#Context db: GraphDatabaseService) {
#Procedure
def alice():String = {
String.valueOf(db.execute( "MATCH (n:User) return n" ));
}
}
Your Scala class declares a constructor with a GraphDatabaseService argument, and the exception tells you that it only wants a no-argument constructor.
It's documented in both
the user documentation:
Only static fields and #Context-annotated fields are allowed in Procedure classes.
the Javadoc:
The procedure method itself can contain arbitrary Java code - but in order to work with the underlying graph, it must have access to the graph API. This is done by declaring fields in the procedure class, and annotating them with the Context annotation. Fields declared this way are automatically injected with the requested resource. This is how procedures gain access to APIs to do work with.
All fields in the class containing the procedure declaration must either be static; or it must be public, non-final and annotated with Context.
Apparently it's not possible to create a class with a public field in Scala, so you'll have to create a parent Java class with the public field, and extend it with your Scala class:
// ProcedureAdapter.java
public abstract class ScalaProcedureAdapter {
#Context
public GraphDatabaseService db;
}
// neoscala.scala
class neoscala extends ScalaProcedureAdapter {
// ...
}
Here is the solution for this :
We will create Class in scala :
class FullTextIndex extends JavaHelper {
#Procedure("example.search")
#PerformsWrites
def search(#Name("label") label: String,
#Name("query") query: String): Stream[SearchHit] = {
//declare your method
}
val nodes: Stream[Node] = db.index.forNodes(index).query(query).stream
val newFunction: java.util.function.Function[Node, SearchHit] = (node: Node) => new SearchHit(node)
nodes.map {
newFunction
}
}
private def indexName(label: String): String = {
"label-" + label
}
}
Procedure in Neo4j always return result in Stream and it is a latest feature in Java8 so we will also used Java Class for return the final result and For defining the public variable.
We will create Java class for result :
public class JavaHelper {
#Context
public GraphDatabaseService db;
#Context
public Log log;
public static class SearchHit {
//your result code here
}
You can refer knoldus blog for Neo4j User Defined Procedure for creating and storing Neo4j Procedure with Scala. Here you will also find sample code with git hub repository.

Configure JAX-RS base URI programmatically per deployment

Im trying to use CDI extensions to discover JAX-RS resources at runtime and automatically publish them under different base URIs in a Java SE environment. Applications should not need to extend javax.ws.rs.core.Application themselves if possible.
I have read RestEasy documentation and javadoc but failed to find any obvious way to modify the #ApplicationPath at runtime.
One idea that im exploring is to try generate javax.ws.rs.core.Application and set the #ApplicationPath base URI programmatically, maybe by using an AnnotatedType CDI extension, and publish that as a * org.jboss.resteasy.spi.ResteasyDeployment`.
Are there other/better ways to do this?
EDIT:
Trying CDI extension event ProcessAnnotatedType to change #javax.ws.rs.Path of JAX-RS resources.
<X> void process(#Observes ProcessAnnotatedType<X> pat) {
if (!pat.getAnnotatedType().isAnnotationPresent(javax.ws.rs.Path.class)) {
return;
}
final AnnotatedType<X> org = pat.getAnnotatedType();
AnnotatedType<X> wrapped = new AnnotatedType<X>() {
#Override
public <T extends Annotation> T getAnnotation(final Class<T> annotation) {
if (javax.ws.rs.Path.class.equals(annotation)) {
class PathLiteral extends AnnotationLiteral<javax.ws.rs.Path> implements javax.ws.rs.Path {
#Override
public String value() {
return "change_me/" + (javax.ws.rs.Path) org.getAnnotation(annotation);
}
}
return (T) new PathLiteral();
} else {
return org.getAnnotation(annotation);
}
}
pat.setAnnotatedType(wrapped);
}
... then after bootstrap, constructing the bean using javax.enterprise.inject.spi.BeanManager was expecting the following code to print "change_me/...."
Set<Bean<?>> beans = beanManager.getBeans(jaxrsClass);
for (Bean<?> bean : beans) {
CreationalContext cc = bm.createCreationalContext(bean);
Object jaxrs = bean.create(cc);
Path p = jaxrs.getClass().getAnnotation(Path.class);
System.out.println(p.value());
}
... but this does not work. javax.ws.rs.Path is unchanged for JAX-RS resource 'jaxrsClass'.
What is wrong?
I doubt this can be done in a reliable way. It probably all comes down to which happens first: the CDI bootstrap or JAX-RS, of course in the future or in other application servers it could all be done in parallel.
It's certainly a cool idea though. What have they said on the RestEasy forums?
We are already using such an approach.
We are using the feature to use Subresource locators and take the power of guice.
At the startup we are scanning the classpath for all resources annotated with #Path. After that we are extracting the path and binding the resources with the help of Names/#Named. So the resources can later be injected with the help of the name.
bind(..).annotatedWith(Names.named("path")).to(..)
The next step is that you need a resource with a subresource locator.
#Path("{name}")
public Object find(#PathParam("name") name){
return injector.getInstance(..);
}
You could use this approach to bind them at runtime and also to change the original annotated path.

Jetty Bind DataSource in JNDI Context

I would like to bind DataSource object to (eclipse) jetty's JNDI context programatically. I need for testing purpose. Here's a piece of code I have now:
server = new Server(SERVER_PORT);
webAppContext = new WebAppContext();
webAppContext.setResourceBase(".");
webAppContext.setContextPath("/" + SERVER_CONTEXT);
webAppContext.addEventListener(prepareServletContextListener());
webAppContext.addFilter(GuiceFilter.class, "/*", null);
webAppContext.addServlet(DefaultServlet.class, "/");
Resource r = new Resource(webAppContext,"jdbc/testDS",createDataSource());
server.setHandler(webAppContext);
server.start();
Of course the line with Resource isn't working.I have no idea how to bind it programatically to obtain sth similar to:
<New id="DSTest" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg></Arg>
<Arg>jdbc/DSTest</Arg>
<Arg>
<New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
<Set name="Url">jdbc:mysql://localhost:3306/databasename</Set>
<Set name="User">user</Set>
<Set name="Password">pass</Set>
</New>
</Arg>
</New>
Any help would be greatly appreciated.
you need to add the defined resource object as attribute to the server object.
The following should work:
Resource r = new Resource("jdbc/testDS",createDataSource());
server.setAttribute("myDs", r);
I encountered the same issue and here is what I did to fix it:
server = new Server(PORT);
WebAppContext context = new WebAppContext();
context.setContextPath(CONTEXT);
context.setConfigurationClasses(new String[] { "org.eclipse.jetty.plus.webapp.PlusConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration" });
// A filter needed by Guice, but this is independent
context.addFilter(GuiceFilter.class, "/*", 0);
PGSimpleDataSource simpleDataSource = new PGSimpleDataSource();
simpleDataSource.setDatabaseName("db-name");
simpleDataSource.setUser("user");
simpleDataSource.setPassword("pwd");
String jndiName = "jdbc/myDS";
Resource resource = new Resource("java:comp/env/" + jndiName, simpleDataSource);
server.setHandler(context);
// an event listener (because I use Guice, but this is independent)
GuiceServletConfig guiceServletConfig = new GuiceServletConfig();
context.addEventListener(guiceServletConfig);
server.start();
This requires to have the following additional libraries:
jetty-jndi
jetty-plus
I tested this code on Embedded Jetty 7 (7.6.10.v20130312)
The topic is old but I have encountered the same issue. Unfortunately existing answers provide no solution.
When you create a Resource specifying an instance of the DataSource, Jetty will not provide this instance when JNDI resource is requested. Instead constructor of Resource makes an attempt to transform the instance to some kind of "recipe" (javax.naming.Reference to be precise) that tells how to build the new instance of configuration with exact same internals.
It works well in case of basic classes but fails to recreate complex data structures (it failed with List<String> in my case). So you end up not getting:
the exact same instance (as you expect of a singleton)
the exact equivalent of the instance (as you expect of properly working JNDI)
I have implemented a wrapper that allows providing the instance specified when creating the Resource.
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
public class ExistingInstanceReference extends Reference implements ObjectFactory {
private Object instance;
private static final long serialVersionUID = -2718709718400909747L;
public ExistingInstanceReference() {
super(null);
}
public ExistingInstanceReference(Object instance) {
super(instance.getClass().getName(), ExistingInstanceReference.class.getName(), null);
this.instance = instance;
}
#Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
if (obj == null) {
return null;
}
ExistingInstanceReference reference = (ExistingInstanceReference) obj;
return reference.instance;
}
}
Note that this implementation fails to comply with Serializable interface as instance variable may contain non-serializable object.
Usage:
Resource r = new Resource(webAppContext, "jdbc/testDS", new ExistingInstanceReference(createDataSource()));
Please, consider this solution as a workaround because the real issue is still to be fixed somewhere in Jetty's sources. Unfortunately I have no time to trace this misbehavior to the root.
In addition, I had to set webAppContext.setParentLoaderPriority(true) because the webapp's classloader didn't see ExistingInstanceReference class in my setup.

MEF: how to import from an exported object?

I have created a MEF plugin control that I import into my app. Now, I want the plugin to be able to import parts from the app. I can't figure how setup the catalog in the plugin, so that it can find the exports from the app. Can somebody tell me how this is done? Below is my code which doesn't work when I try to create an AssemblyCatalog with the current executing assembly.
[Export(typeof(IPluginControl))]
public partial class MyPluginControl : UserControl, IPluginControl
[Import]
public string Message { get; set; }
public MyPluginControl()
{
InitializeComponent();
Initialize();
}
private void Initialize()
{
AggregateCatalog catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer container = new CompositionContainer(catalog);
try
{
container.ComposeParts(this);
}
catch (CompositionException ex)
{
Console.WriteLine(ex.ToString());
}
}
}
You don't need to do this.
Just make sure that the catalog you're using when you import this plugin includes the main application's assembly.
When MEF constructs your type in order to export it (to fulfill the IPluginControl import elsewhere), it'll already compose this part for you - and at that point, will import the "Message" string (though, you most likely should assign a name to that "message", or a custom type of some sort - otherwise, it'll just import a string, and you can only use a single "string" export anywhere in your application).
When MEF composes parts, it finds all types matching the specified type (in this case IPluginControl), instantiates a single object, fills any [Import] requirements for that object (which is why you don't need to compose this in your constructor), then assigns it to any objects importing the type.