I am writing a Java class to browse a Tibco EMS JMS server and show all queues. I'm able to connect without issues and browse specific queues but I am looking for a way to return a list of all queues (with queue depth if possible). I'm not if there is a specific EMS API to use so I am using standard JMS.
I've tried the following code to do a reverse JNDI lookup but it is failing.
NamingEnumeration<?> queues = context.list("");
List<String> availableQueuesNames = new ArrayList<String>();
while (queues.hasMoreElements()) {
NameClassPair element = (NameClassPair) queues.nextElement();
availableQueuesNames.add(element.getName());
}
Which throws this error:
javax.naming.OperationNotSupportedException: Not supported
at com.tibco.tibjms.naming.TibjmsContext.list(TibjmsContext.java:1018)
at com.tibco.tibjms.naming.TibjmsContext.list(TibjmsContext.java:484)
at javax.naming.InitialContext.list(Unknown Source)
I did some digging and it seems Tibco EMS does not support looking into the JNDI like this. Is there another way to accomplish this?
Using the tibjmsServerAdministrator.java same class provided with Tibco as a guide (and the addAdmin() method), I was able to write code to list all queues:
Map<String, TibjmsAdmin> map = new HashMap<String, TibjmsAdmin>();
addAdmin(txtServer.getText(), txtUser.getText(), txtPassword.getText(), map);
_admin = new TibjmsAdmin[map.size()];
map.values().toArray(_admin);
QueueInfo[] info = _admin[0].getQueues(null);
for (int i = 0; i < info.length; i++) {
String queueName = info[i].getName();
if (!queueName.startsWith("$") && !queueName.startsWith(">")) {
queues.add(queueName + ", 0");
}
}
I'm not sure about Tibco details, but maybe it would work with listBindings instead of list?
I have done the same thing in a generic way like this:
List<Queue> out = new ArrayList<>();
scanJndiForQueues(out, "");
...
private void scanJndiForQueues(List<Queue> out, String path) throws NamingException {
InitialContext context = new InitialContext();
Object resource = context.lookup(path);
if (isSubContext(resource)) {
NamingEnumeration<Binding> list = context.listBindings(path);
while (list.hasMoreElements()) {
Binding binding = list.nextElement();
scanJndiForQueues(out, path + "/" + binding.getName());
}
} else if (resource instanceof Queue) {
out.add((Queue) resource);
} // else ignore Topics
}
private boolean isSubContext(Object object) {
return javax.naming.Context.class.isAssignableFrom(object.getClass());
}
Don't know why you need to list all the EMS queues, but you can achieve this (and many other things) with the GEMS tool.
Search for it at tibcommunity (you will need an account), or you can download the last version directly from here.
Related
I am learning Amazon Cloud Search but I couldn't find any code in either C# or Java (though I am creating in C# but if I can get code in Java then I can try converting in C#).
This is just 1 code I found in C#: https://github.com/Sitefinity-SDK/amazon-cloud-search-sample/tree/master/SitefinityWebApp.
This is 1 method i found in this code:
public IResultSet Search(ISearchQuery query)
{
AmazonCloudSearchDomainConfig config = new AmazonCloudSearchDomainConfig();
config.ServiceURL = "http://search-index2-cdduimbipgk3rpnfgny6posyzy.eu-west-1.cloudsearch.amazonaws.com/";
AmazonCloudSearchDomainClient domainClient = new AmazonCloudSearchDomainClient("AKIAJ6MPIX37TLIXW7HQ", "DnrFrw9ZEr7g4Svh0rh6z+s3PxMaypl607eEUehQ", config);
SearchRequest searchRequest = new SearchRequest();
List<string> suggestions = new List<string>();
StringBuilder highlights = new StringBuilder();
highlights.Append("{\'");
if (query == null)
throw new ArgumentNullException("query");
foreach (var field in query.HighlightedFields)
{
if (highlights.Length > 2)
{
highlights.Append(", \'");
}
highlights.Append(field.ToUpperInvariant());
highlights.Append("\':{} ");
SuggestRequest suggestRequest = new SuggestRequest();
Suggester suggester = new Suggester();
suggester.SuggesterName = field.ToUpperInvariant() + "_suggester";
suggestRequest.Suggester = suggester.SuggesterName;
suggestRequest.Size = query.Take;
suggestRequest.Query = query.Text;
SuggestResponse suggestion = domainClient.Suggest(suggestRequest);
foreach (var suggest in suggestion.Suggest.Suggestions)
{
suggestions.Add(suggest.Suggestion);
}
}
highlights.Append("}");
if (query.Filter != null)
{
searchRequest.FilterQuery = this.BuildQueryFilter(query.Filter);
}
if (query.OrderBy != null)
{
searchRequest.Sort = string.Join(",", query.OrderBy);
}
if (query.Take > 0)
{
searchRequest.Size = query.Take;
}
if (query.Skip > 0)
{
searchRequest.Start = query.Skip;
}
searchRequest.Highlight = highlights.ToString();
searchRequest.Query = query.Text;
searchRequest.QueryParser = QueryParser.Simple;
var result = domainClient.Search(searchRequest).SearchResult;
//var result = domainClient.Search(searchRequest).SearchResult;
return new AmazonResultSet(result, suggestions);
}
I have already created domain in Amazon Cloud Search using AWS console and uploaded document using Amazon predefine configuration option that is movie Imdb json file provided by Amazon for demo.
But in this method I am not getting how to use this method, like if I want to search Director name then how do I pass in this method as because this method parameter is of type ISearchQuery?
I'd suggest using the official AWS CloudSearch .NET SDK. The library you were looking at seems fine (although I haven't look at it any detail) but the official version is more likely to expose new CloudSearch features as soon as they're released, will be supported if you need to talk to AWS support, etc, etc.
Specifically, take a look at the SearchRequest class -- all its params are strings so I think that obviates your question about ISearchQuery.
I wasn't able to find an example of a query in .NET but this shows someone uploading docs using the AWS .NET SDK. It's essentially the same procedure as querying: creating and configuring a Request object and passing it to the client.
EDIT:
Since you're still having a hard time, here's an example. Bear in mind that I am unfamiliar with C# and have not attempted to run or even compile this but I think it should at least be close to working. It's based off looking at the docs at http://docs.aws.amazon.com/sdkfornet/v3/apidocs/
// Configure the Client that you'll use to make search requests
string queryUrl = #"http://search-<domainname>-xxxxxxxxxxxxxxxxxxxxxxxxxx.us-east-1.cloudsearch.amazonaws.com";
AmazonCloudSearchDomainClient searchClient = new AmazonCloudSearchDomainClient(queryUrl);
// Configure a search request with your query
SearchRequest searchRequest = new SearchRequest();
searchRequest.Query = "potato";
// TODO Set your other params like parser, suggester, etc
// Submit your request via the client and get back a response containing search results
SearchResponse searchResponse = searchClient.Search(searchRequest);
Is there any way to Iterate all described services in routes file? URL and HTTP methods are needed.
I need this feature for running some integration test.
I am using Play for Java.
Not easily. I managed to hack my way through it a while ago(no scala know-how). I'll post that code maybe it can be of use.
public static List<String[]> parseRoutes() {
scala.Option<play.core.Router.Routes> option = Play.application().getWrappedApplication().routes();
if (option.isDefined()) {
play.core.Router.Routes routes = option.get();
scala.collection.Seq<scala.Tuple3<String, String, String>> doc = routes.documentation();
scala.collection.Iterator<scala.Tuple3<String, String, String>> it = doc.iterator();
List<String[]> listOfRoutes = new ArrayList<String[]>();
while(it.hasNext()) {
scala.Tuple3<String, String, String> tuple = it.next();
//tuple._1() is the method and tuple._2() the url... tuple._3() is the controller name
String[] route = {tuple._1(), tuple._2()};
listOfRoutes.add(route);
Logger.debug("route -> " + Arrays.toString(route));
}
return listOfRoutes;
}
return null;
}
Don't worry about the .iterator() showing a The method iterator() is ambiguous for the type Seq<Tuple3<String,String,String>>. It compiles just fine in play.
I'm trying to run:
Map<String, String> environmentProperties = new HashMap<String, String>();
environmentProperties.put("java.naming.security.authentication", "simple");
environmentProperties.put("java.naming.ldap.attributes.binary", "tokenGroups objectSid");
LdapContextSource contextSource = new LdapContextSource();
contextSource.setAnonymousReadOnly(false);
contextSource.setPooled(false);
contextSource.setUserDn("CN=Administrator,CN=Users,DC=someDomain,DC=com");
contextSource.setPassword("password");
contextSource.setUrls(new String[]{"ldap://url.goes.here"});
contextSource.setBaseEnvironmentProperties(environmentProperties);
contextSource.setDirObjectFactory(null);
contextSource.afterPropertiesSet();
final SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
ContextExecutor contextExecutor = new ContextExecutor() {
public Object executeWithContext(DirContext ctx) throws NamingException {
EventDirContext ectx = (EventDirContext) ctx.lookup("CN=Users,,DC=someDomain,DC=com");
ectx.addNamingListener("", "(cn=*)", searchControls, new LDAPChangeListener());
return null;
}
};
LdapTemplate ldapTemplate = new LdapTemplate(contextSource);
ldapTemplate.setIgnorePartialResultException(true);
ldapTemplate.executeReadOnly(contextExecutor);
but, the first message my listener gets is:
javax.naming.OperationNotSupportedException: [LDAP: error code 12 - 00000057: LdapErr: DSID-0C090753, comment: Error processing control, data 0, v1db1 ]; remaining name ''
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3127)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3013)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2820)
at com.sun.jndi.ldap.LdapNamingEnumeration.getNextBatch(LdapNamingEnumeration.java:129)
I also ran this code I found here that's supposed to verify that my AD supports persistent search, and the result was true.
static boolean isPersistentSearchSupported(LdapContext rootContext)
throws NamingException {
SearchResult rootDSE;
NamingEnumeration searchResults;
Attributes attrs;
NamingEnumeration attrEnum;
Attribute attr;
NamingEnumeration values;
String value;
String[] attrNames = { "supportedControl" };
SearchControls searchControls = new SearchControls();
searchControls.setCountLimit(0); // 0 means no limit
searchControls.setReturningAttributes(attrNames);
searchControls.setSearchScope(SearchControls.OBJECT_SCOPE);
// search for the rootDSE object
searchResults = rootContext.search("", "(objectClass=*)",
searchControls);
while (searchResults.hasMore()) {
rootDSE = (SearchResult) searchResults.next();
attrs = rootDSE.getAttributes();
attrEnum = attrs.getAll();
while (attrEnum.hasMore()) {
attr = (Attribute) attrEnum.next();
values = attr.getAll();
while (values.hasMore()) {
value = (String) values.next();
if (value.equals("1.2.840.113556.1.4.528"))
return true;
}
}
}
return false;
}
what do I need to do to start getting events from AD?
According to the documentation, the scope can't be Subtree and the search filter must be (objectClass=*) for a persistent search.
UPDATE:
I found this: https://forums.oracle.com/thread/1157474?tstart=0
It basically says that AD does not support this, and that there’s no way I can make the above code work.
However, it does give out 2 different ways of getting such notifications from AD:
Using DirSync- I tried the attached code, and it did not work, but did not continue investigating from the reasons that will be listed in the end of this post.
Using LDAP Notifications (https://forums.oracle.com/message/4698114 )- this code worked, however, it only returns results for created / changed events, it will not notify once an object gets deleted, and there’s no way of getting it with this method since the search filter cannot be changed, because any other filter will not work. So it did not fit my purposes, but maybe someone else finds it useful.
I thought DirSync might be the only solution possible for me, if any.
However, it should be noted that DirSync has the following limitations:
The DirSync control can only be used by a highly privileged account, such as a domain administrator.
The DirSync control can only monitor an entire naming context. You cannot limit the scope of a DirSync search to monitor only a specific subtree, container, or object in a naming context.
I hope this information will help someone else in the future.
I would like to add some additional information on this topic since I have done research on this topic couple years ago.
The NamingListener capability provided by JNDI. If you try to register a NamingListener on any LDAP server, that particularly server must support the 'Persistent Search' extension. The Persistent Search extension has always been in IETF draft stage therefore there's no official RFC# associate with it.
Not a lot of LDAP server support this extension. The last time I researched on this topic was 2008 and the LDAP servers that support persistent search extension were 389 Directory Server, Oracle Internet Directory (OID) and OpenDS (now known as OpenDJ).
http://www-archive.mozilla.org/directory/ietf-docs/draft-smith-psearch-ldap-01.txt
http://www.redhat.com/archives/fedora-directory-users/2008-May/msg00120.html
I'm developing an Web JEE5 Application, I need to log the http post and get parameters, What is the best way?
At the beginning I tried with HttpRequest->getQueryString, but it doesn't work with post parameters,
then I wrote a code that uses HttpRequest->getParameterMap (see below)
Map<String,String[]> parametersName=theRequest.getParameterMap();
int count=0;
for (String paramName : parametersName.keySet()) {
String[] paramValues=parametersName.get(paramName);
if(count>0)
allParameter.append("&");
allParameter.append(paramName);
allParameter.append("=");
for (int i = 0; i < paramValues.length; i++) {
allParameter.append(paramValues[i]);
if(paramValues.length>1)
allParameter.append(",");
}
count++;
}
It works but it seems too complicated (compared with getQueryString) for the works to do.
Is there a better/faster way?
All HTTP (and application servers) support access.log - the log file that stores the HTTP requests and responses details. Just configure it.
you can also do it like this:
Enumeration parms = request.getHeaderNames();
String parmname;
String parmval;
while (parms.hasMoreElements()) {
parmname = (String)parms.nextElement();
parmval = request.getHeader(parmname);
Logger.log(parmname + " - " + parmval);
}
I'm implementing a servlet as a JMX manager that runs in the same instance of Tomcat that all of the monitored servlets are running in. I can see the data of the monitored servlets when I open JConsole. From within my manager servlet I can enumerate all of the available standard MBeans, including the ones I've created in the monitored servlets, using this code like this:
JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi://localhost:1099/jndi/rmi://localhost:1099/jmxrmi" );
mConnector = JMXConnectorFactory.connect( url );
mMBSC = mConnector.getMBeanServerConnection();
mObjectName = new ObjectName( "com.blahCompany.blah.blah:type=BlahBlah" );
// just looking for one specific bean
Set<ObjectName> myMbean = mMBSC.queryNames( mObjectName, null );
if( myMBean.size() == 1 ) // I know it exists
{
MBeanInfo mbeanInfo = mMBSC.getMBeanInfo( <ObjectName extracted from Set> );
MBeanAttributeInfo[] mbeanAttributeInfos = mbeanInfo.getAttributes();
for( MBeanAttributeInfo attribInfo : mbeanAttributeInfos )
{
if( attribInfo.isReadable() )
{
String attribName = attribInfo.getName();
String attribReturnType = attribInfo.getType();
// The data's somewhere ... where????
// In the MBeanInfo?
// In the MBeanAttributeInfo??
}
}
}
The problem is I don't know how to actually extract the data from these MBeans. The answer must be godawful obvious because no one else seems to have asked, but I do have a gift for overlooking the obvious. Your help will be gratefully appreciated.
Bill
All you need to do is something like the below:
Object value = mMBSC.getAttribute(objectName, attributeName);
Or create a proxy object that gets an instance of the MBean interface and allows you to access it that way. A tutorial on how to do this is here: http://docs.oracle.com/javase/tutorial/jmx/remote/custom.html
One note, this is assuming a remote connection, but from your question it seems your are accessing the beans locally? If that is the case then you can use platform.getMBeanServer() to get access to the MBeanServer more directly. E.g. MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();