Create a new mixin in sling - java

I am having trouble create a new custom type to the jackrabbit in apache sling using the below code. This worked fine straight on Jackrabbit but not on Apache Sling. Am I doing this correctly for sling? Thanks
The following code gives me a "javax.jcr.InvalidItemStateException: Conflict". I am using a standalone sling and am the only user so there is definitely no conflict.
Repository repository = JcrUtils.getRepository("http://localhost:8080/server");
Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
NamespaceRegistry registry = session.getWorkspace().getNamespaceRegistry();
registry.registerNamespace("my", "http://my.com/v1.0");
CndImporter.registerNodeTypes(new FileReader("C:\\test.cnd"), session);

If you're using Sling, you can avoid all this by putting your CND file in an OSGi bundle (where your java code should reside anyway), with a header that tells Sling where to find it.
Your node types will then be registered automatically when your bundle is activated. For an example of this see the event.cnd file which is declared in a Sling-Nodetypes bundle header that's set in that module's pom.xml (or in any other way if you're not using Maven).
Note also that you shouldn't need JcrUtils.getRepository in Sling anyway, the right way to get a repository is via the SlingRepository OSGi service, which takes care of repository login and configuration in a consistent way for all your Sling components. You can get the repository via a #Reference to a SlingRepository in java code, or get a JCR Session from the Resource that Sling provides to request handlers like servlets and scripts. The Slingbucks sample uses both mechanisms.

The JavaDocs for InvalidItemStateException offer this clue:
Exception thrown by the write methods of Node and Property and by save
and refresh if an attempted change would conflict with a change to the
persistent workspace made through another Session. Also thrown by
methods of Node and Property if that object represents an item that
has been removed from the workspace.
Are you sure that you don't have any old sessions still running, perhaps is a daemon process that hasn't been shut down properly?

Related

Configuring cxf service listing in karaf

It is a web service deployed on Apache Karaf using camel-cxf. I am able to see the cxf service listing in URL localhost:8181/cxf which has some rest and soap services deployed on it.
The problem is it is returning the service listing whenever any request comes with keyword "services". For example the url http://localhost:8181/abcd/services returns cxf service listing page instead of processing the actual request.
I got to know from http://cxf.apache.org/docs/jaxrs-services-description.html that its is because of the default value of service-list-path of CXFServet is services.
Here is my Question. If I want to override this, I should set this property in etc/org.apache.cxf.osgi.cfg. This cfg file is not present under etc folder in my karaf. What are the steps to be taken if I am creating this property file manually? What features I need to install? Or creating this cfg is sufficient ?
Appreciate your help !
There should be no extra installation requirements, just create a new file etc/org.apache.cxf.osgi.cfg.
There are three settings you may be interested in:
org.apache.cxf.servlet.context = /mycxf
org.apache.cxf.servlet.service-list-path = /myservices
org.apache.cxf.servlet.hide-service-list-page = false
Where the default URL for the CXF service listing is usually like http://localhost:8181/cxf/services, with the changes above the URL would become http://localhost:8181/mycxf/myservices
If you change from false (default value) to true, then your services will be hidden and you will instead get a page stating No service was found.
Because these are initialisation settings you need to shut down Karaf for the changes to apply.
I see several points here --
The CXF framework is installed by default in karaf under the context-path /cxf.
/cxf/services can be considered as a CXF internal app that displays the list of services deployed in CXF. I don't think you can configure the name "services" here (and why would you change that?)
the "url-pattern in web.xml" you speak of (if I understand correctly) determines the context path of your servlet/application. You can specify this is camel like this:
<cxf:rsServer id="secureRsServer" address="https://0.0.0.0:8182/my/path/"
serviceClass="....">
(for the RS Server, probably same for the WS server).

Adding custom nodetypes to Apache Sling WebApp

I'm trying to figure out a way to add custom nodetypes using a CND file to my Sling WebApp. I downloaded the WAR file and got it running but since all the code is already compiled (as .class files), I can't add code to read the CND file and add the custom nodetypes.
On a separate note, I do have Jackrabbit running and with it, I can use the JackrabbitNodeTypeManager or other ways to code reading a CND file and adding nodetypes. This works on my local repository that is not running on a server.
I want to be able to add new nodetypes to the Sling Web Application in a similar way. So I'll boil my questions down to:
Is there a way to code the addition of new nodetypes in the Sling WebApp?
How can I connect my Jackrabbit repository (local) to the Sling Web Application (on server) so that I can possibly explore adding custom nodetypes this way (as I'm doing on my Jackrabbit repo locally at the moment)?
I understand that Sling is a framework that uses Jackrabbit as a repo and provides REST-like services to work with the repository, but I imagine there's a way to add these custom nodetypes just like Jackrabbit allows.
Thanks.
Is there a way to code the addition of new nodetypes in the Sling WebApp?
This is documented at Declared Node Type Registration. What you need to do is
write the node type definition in CND format
place it in a bundle
reference the file in the manifest using the Sling-Nodetypes header
deploy the bundle to your Sling app

Replace default resourceBundle and resourceControl implementations in JSP web application

in an existing Web Application (JSP, Struts), localizations are managed through JSTL tags fmt:setbundle, fmt:message and .properties files.
I'd like to get rid of the .properties files and use an alternative datasource for localizations.
For my goal I've created custom ResourceBundle and ResourceControl implementations (details on where data is picked, xml, database, are out of scope), but I'm wondering how to register and use them in place of the default/factory file-based implementation, so I'm not forced to modify markup code (fmt:message...) among web application files.
I saw examples that point to replace fmtResourceKey session value but it's limited to only one bundle and it looks like an "hack".
Any good ideas?
Thanks for your help!
Ok, it seems I sorted out with subclassing/customizing java.util.ResourceBundle, which also carries implementantion of custom ResourceBundleControl and ResourceBundleControlProvider (injected through Service Provider Interface - SPI).
Similar solution is depicted in this page from Oracle:
https://docs.oracle.com/javase/tutorial/i18n/serviceproviders/resourcebundlecontrolprovider.html
but was lacking an important hint: "put your JAR inside VM" since ResourceBundle.GetBundle method internally uses Serviceloader.LoadInstalled which searches for custom provider installed inside Java VM, as stated in LoadInstalled documentation:
This method is intended for use when only installed providers are
desired. The resulting servicewill only find and load providers that
have been installed into the current Java virtual machine; providers
on the application's class path will be ignored.
Thanks!

hazelcast : changing configuration programatically doesnt work

I am unable to configure/change the Map(declared as part of hazelcast config in spring) properties after hazelcast instance start up. I am using hazelcast integrated with spring as hibernate second level cache. I am trying to configure the properties of map (like TTL) in an init method (PostConstruct annotated) which is called during spring bean initialization.
There is not enough Documentation , if there is please guide me to it.
Mean while i went through this post and found this Hazelcast MapStoreConfig ignored
But how does the management center changes the config, will it recreate a new instance again ?
Is hazelcast Instance light weight unlike session factory ? i assume not,
please share your thoughts
This is not yet supported. JCache is the only on-the-fly configuration data structure at the moment.
However you'll most probably be able to destroy a proxy (DistributedObject like IMap, IQueue, ...), reconfigure it and recreate it. Anyhow at the time of recreation you must make sure that every node sees the same configuration, for example by storing the configuration itself inside an IMap or something like that. You'll have to do some wrapping on your own.
PS: This is not officially supported and an implementation detail that might change at later versions!
PPS: This feature is on the roadmap for quite some time but didn't made it into a release version yet, it however is still expected to have full support at some time in the future.

In Java, how to reload dynamically resources bundles in a web application?

We are using fmt:setBundle to load a resource bundle from a database (we extended the ResourceBundle class to do that).
When we modify a value in database, we have to reload the web server to display the new value on the web app.
Is there any simple way to use the new value without restarting the web server ?
(We do not want to always look up the value from database but we would like to invalidate the cache, for example by calling a special 'admin' URL)
EDIT : We are using JDK 1.4, so I would prefer a solution on that version. :)
If you're using JDK 1.6 you can use the callback methods getTimeToLive() and needsReload() in ResourceBundle.Control to control if the bundle cache needs to be loaded with new values from the database.
As others have pointed out in the comments, you might want to look into Spring - particularly the ReloadableResourceBundleMessageSource.
First you can create a class which extends from ReloadableResourceBundleMessageSource to expose its inner class protected method called getProperties. This method return a concurrent map from PropertiesHolder object. Second you should configure a bean of that extended class in you web configuration class. Now you able to use messageSource in your service or business layer. Here is the reference link Configure reloadable message source bundle

Categories