Calling an Enterprise bean method - ejb

Here's my Bean class source
#Stateless(mappedName="StringVal")
public class NewSessionBean implements NewSessionRemote {
String val = null;
public String stringChange(int parameter) {
while(parameter < 5){
switch (parameter){
case 1: System.out.println(val + "One" + ",");
case 2: System.out.println(val + "Two" + ",");
case 3: System.out.println(val + "Three" + ",");
case 4: System.out.println(val + "Four" + ",");
}
}
return val;
}
}
And here's my client class for this bean (Stand Alone Client)
import endpoint.NewSessionRemote;
import javax.naming.InitialContext;
public class TestLogicBean {
static String retVal = null;
public static void main(String[] args) {
try {
InitialContext ctx = new InitialContext();
NewSessionRemote br = (NewSessionRemote) ctx.lookup("StringVal");
for (int i = 0; i < 5; i++) {
String retVal1 = br.stringChange(i);
System.out.println("EJB message is:" + retVal1);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
But i'm getting this Exception "javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial"
I have tried several ways to make this,but still it gives this exception.

Look what I found:
http://www.jboss.org/index.html?module=bb&op=viewtopic&t=38107
Seems like you have to had this to your jndi.properties:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Looks like it's all about setting up the connection to the JNDI server.

Related

Confluent Kafka consumer consumes messages only after changing groupId

I have a .Net core console application, that uses Confluent.Kafka.
I build a consumer for consuming messages from specific topic.
the app is intended to run a few times every-day, consume the messages on the specified topic and process them.
It took me a while to understand the consumer's vehavior, but the it will consume messages only if its groupId is a one that was never in use before.
Every time I change the consumer's groupId - the comsumer will fetch the messages in the subscribed topic. But on the next runs - with same groupId - the consumer.Consume returns null.
This behvior seems rlated to rebalance between consumers on same group. But I don't understand why - since the consumer should exist only throughout the application liftime. Before leaving the app, I call to consumer.close() and consumer.Dispose(). These should destoy the consumer, so that on the next run, when I create the consumer, again it will be the first and single consumer on the specified groupId. But as I said, this is not what happens in fact.
I know there are messages on the topic - I check it via command-line. And I also made sure the topic has only 1 partition.
The most weird thing is, that I have another .net core console app, which does the same process - and with no issue at all.
I attach the codes of the 2 apps.
Working app - always consuming:
class Program
{
...
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Please provide topic name to read and SMTP topic name");
}
else
{
var services = new ServiceCollection();
services.AddSingleton<ConsumerConfig, ConsumerConfig>();
services.AddSingleton<ProducerConfig, ProducerConfig>();
var serviceProvider = services.BuildServiceProvider();
var cConfig = serviceProvider.GetService<ConsumerConfig>();
var pConfig = serviceProvider.GetService<ProducerConfig>();
cConfig.BootstrapServers = Environment.GetEnvironmentVariable("consumer_bootstrap_servers");
cConfig.GroupId = "confluence-consumer";
cConfig.EnableAutoCommit = true;
cConfig.StatisticsIntervalMs = 5000;
cConfig.SessionTimeoutMs = 6000;
cConfig.AutoOffsetReset = AutoOffsetReset.Earliest;
cConfig.EnablePartitionEof = true;
pConfig.BootstrapServers = Environment.GetEnvironmentVariable("producer_bootstrap_servers");
var consumer = new ConsumerHelper(cConfig, args[0]);
messages = new Dictionary<string, Dictionary<string, UserMsg>>();
var result = consumer.ReadMessage();
while (result != null && !result.IsPartitionEOF)
{
Console.WriteLine($"Current consumed msg-json: {result.Message.Value}");
...
result = consumer.ReadMessage();
}
consumer.Close();
Console.WriteLine($"Done consuming messages from topic {args[0]}");
}
}
class ConsumerHelper.cs
namespace AggregateMailing
{
using System;
using Confluent.Kafka;
public class ConsumerHelper
{
private string _topicName;
private ConsumerConfig _consumerConfig;
private IConsumer<string, string> _consumer;
public ConsumerHelper(ConsumerConfig consumerConfig, string topicName)
{
try
{
_topicName = topicName;
_consumerConfig = consumerConfig;
var builder = new ConsumerBuilder<string, string>(_consumerConfig);
_consumer = builder.Build();
_consumer.Subscribe(_topicName);
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on ConsumerHelper: {exc.ToString()}");
}
}
public ConsumeResult<string, string> ReadMessage()
{
Console.WriteLine("ReadMessage: start");
try
{
return _consumer.Consume();
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on ReadMessage: {exc.ToString()}");
return null;
}
}
public void Close()
{
Console.WriteLine("Close: start");
try
{
_consumer.Close();
_consumer.Dispose();
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on Close: {exc.ToString()}");
}
}
}
}
Not working app - consuming only on first run after changing consumer groupId to one never in use:
class Program.cs
class Program
{
private static SmtpClient smtpClient;
private static Random random = new Random();
static void Main(string[] args)
{
try
{
var services = new ServiceCollection();
services.AddSingleton<ConsumerConfig, ConsumerConfig>();
services.AddSingleton<SmtpClient>(new SmtpClient("smtp.gmail.com"));
var serviceProvider = services.BuildServiceProvider();
var cConfig = serviceProvider.GetService<ConsumerConfig>();
cConfig.BootstrapServers = Environment.GetEnvironmentVariable("consumer_bootstrap_servers");
cConfig.GroupId = "smtp-consumer";
cConfig.EnableAutoCommit = true;
cConfig.StatisticsIntervalMs = 5000;
cConfig.SessionTimeoutMs = 6000;
cConfig.AutoOffsetReset = AutoOffsetReset.Earliest;
cConfig.EnablePartitionEof = true;
var consumer = new ConsumerHelper(cConfig, args[0]);
...
var result = consumer.ReadMessage();
while (result != null && !result.IsPartitionEOF)
{
Console.WriteLine($"current consumed message: {result.Message.Value}");
var msg = JsonConvert.DeserializeObject<EmailMsg>(result.Message.Value);
result = consumer.ReadMessage();
}
Console.WriteLine("Done sending emails consumed from SMTP topic");
consumer.Close();
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on Main: {exc.ToString()}");
}
}
class ConsumerHelper.cs
using Confluent.Kafka;
using System;
using System.Collections.Generic;
namespace Mailer
{
public class ConsumerHelper
{
private string _topicName;
private ConsumerConfig _consumerConfig;
private IConsumer<string, string> _consumer;
public ConsumerHelper(ConsumerConfig consumerConfig, string topicName)
{
try
{
_topicName = topicName;
_consumerConfig = consumerConfig;
var builder = new ConsumerBuilder<string, string> (_consumerConfig);
_consumer = builder.Build();
_consumer.Subscribe(_topicName);
//_consumer.Assign(new TopicPartition(_topicName, 0));
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on ConsumerHelper: {exc.ToString()}");
}
}
public ConsumeResult<string, string> ReadMessage()
{
Console.WriteLine("ConsumeResult: start");
try
{
return _consumer.Consume();
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on ConsumeResult: {exc.ToString()}");
return null;
}
}
public void Close()
{
Console.WriteLine("Close: start");
try
{
_consumer.Close();
_consumer.Dispose();
}
catch (System.Exception exc)
{
Console.WriteLine($"Error on Close: {exc.ToString()}");
}
Console.WriteLine("Close: end");
}
}
}

Application Insights configuration web API

I have created a library project for writing logs into ApplicationInsights as well as table storage and is being consumed my different other WebAPI projects. But due to some reason the logs are not getting logged in Application Insights but it works with table storage.
private void AddTelemetryTarget(string instrumentationKey, LoggerEnumerations.LogLevel minLogLevel, LoggingConfiguration config)
{
try
{ ConfigurationItemFactory.Default.Targets.RegisterDefinition("ApplicationInsightsTarget", typeof(ApplicationInsightsTarget));
ApplicationInsightsTarget aiTarget = new ApplicationInsightsTarget();
aiTarget.InstrumentationKey = instrumentationKey;
aiTarget.Name = "ai";
var wrapper = new AsyncTargetWrapper(aiTarget, 5000, AsyncTargetWrapperOverflowAction.Grow);
config.AddTarget("TelemetryAsyncWrapper", wrapper);
//Applying logging rules.
LoggingRule rule = new LoggingRule("*", ConvertLogType(minLogLevel), aiTarget);
config.LoggingRules.Add(rule);
}
catch
{ }
}
private LogLevel ConvertLogType(LoggerEnumerations.LogLevel type)
{
switch (type)
{
case LoggerEnumerations.LogLevel.Error: return LogLevel.Error;
case LoggerEnumerations.LogLevel.Info: return LogLevel.Info;
case LoggerEnumerations.LogLevel.Warn: return LogLevel.Warn;
default: return LogLevel.Trace;
}
}
public async Task Log(string message, LoggerEnumerations.LogLevel type, Dictionary<string, string> customParams, Exception ex = null, bool isPayload = false)
{
LogEventInfo eventInfo = PopulateEventInfo(message, type, customParams, ex);
if (!isPayload)
{
_logger.Log(eventInfo);
}
else
{
_payloadLogger.Log(eventInfo);
}
}
private LogEventInfo PopulateEventInfo(string message, LoggerEnumerations.LogLevel type, Dictionary<string, string> customParams, Exception ex = null)
{
LogEventInfo eventInfo = new LogEventInfo();
eventInfo.Level = ConvertLogType(type);
eventInfo.Message = message;
eventInfo.LoggerName = this.GetType().ToString();
if (ex != null)
{
eventInfo.Exception = ex;
}
else if (eventInfo.Level == LogLevel.Error)
{
eventInfo.Exception = new Exception(message);
}
//Adding custom properties to LogEventInfo to display in Application insight
if (customParams != null)
{
foreach (KeyValuePair<string, string> param in customParams)
{
eventInfo.Properties.Add(param.Key, param.Value);
}
}
return eventInfo;
}
Version of Nuget packages are
Microsoft.ApplicationInsights.NLogTarget : 2.13.1
NLog : 4.6.8
Thanks
I added Application Insights as Connected Services and I removed the Instrumentation Key from ApplicationInsights.config file and when registering the nlog target I used instrumentation key from my web.config file and it started working.

How to call EJB from another app on the same server?

I have java SE sample client which run on desktop (code below). But I have access to WebSphere were called EJB is deployed. How to rewrite below code to work on WebSphere? (When I leave this code just like it is program works but I think this can be done more simple and clear)
Main method:
WSConn connection = new WSConn();
final Plan plan = connection.getPlanBean();
com.ibm.websphere.security.auth.WSSubject.doAs(connection.getSubject(), new java.security.PrivilegedAction<Object>() {
public Object run() {
try {
// App logic
} catch (Throwable t) {
System.err.println("PrivilegedAction - Error calling EJB: " + t);
t.printStackTrace();
}
return null;
}
}); // end doAs
WSConn class:
public class WSConn {
private static final String INITIAL_CONTEXT_FACTORY = "com.ibm.websphere.naming.WsnInitialContextFactory";
private static final String JAAS_MODULE = "WSLogin";
private static final String MODEL_EJB_NAME_LONG = "ejb/com/ibm/ModelHome";
private static final String PLAN_EJB_NAME_LONG = "ejb/com/ibm/PlanHome";
private Subject subject;
private InitialContext initialContext;
private String serverName;
private String serverPort;
private String uid;
private String pwd;
private String remoteServerName;
private Model modelBean;
private Plan planBean;
public WSConn() {
Properties props = new Properties();
try {
props.load(WSConn.class.getClassLoader().getResourceAsStream("WSConn.properties"));
} catch (IOException e) {
e.printStackTrace();
}
serverName = props.getProperty("WSConn.serverName");
serverPort = props.getProperty("WSConn.serverPort");
uid = props.getProperty("WSConn.userID");
pwd = props.getProperty("WSConn.password");
remoteServerName = props.getProperty("WSConn.remoteServerName");
}
private void init() {
if (subject == null || initialContext == null) {
subject = login();
}
}
private Subject login() {
Subject subject = null;
try {
LoginContext lc = null;
// CRATE LOGIN CONTEXT
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
env.put(Context.PROVIDER_URL, "corbaloc:iiop:" + serverName + ":" + serverPort);
initialContext = new InitialContext(env);
// Just to test the connection
initialContext.lookup("");
lc = new LoginContext(JAAS_MODULE, new WSCallbackHandlerImpl(uid, pwd));
lc.login();
subject = lc.getSubject();
} catch (javax.naming.NoPermissionException exc) {
System.err.println("[WSConn] - Login Error: " + exc);
} catch (Exception exc) {
System.err.println("[WSConn] - Error: " + exc);
}
return subject;
}
public wModel getModelBean() {
if (modelBean == null) {
init();
modelBean = (wModel) com.ibm.websphere.security.auth.WSSubject.doAs(subject,
new java.security.PrivilegedAction<wModel>() {
public wModel run() {
wModel session = null;
try {
Object o = initialContext.lookup(MODEL_EJB_NAME_LONG);
wModelHome home = (wModelHome) PortableRemoteObject.narrow(o, wModelHome.class);
if (home != null) {
session = home.create(remoteServerName);
}
} catch (Exception exc) {
System.err.println("Error getting model bean: " + exc);
}
return session;
}
}); // end doAs
}
return modelBean;
}
public wPlan getPlanBean() {
if (planBean == null) {
init();
planBean = (wPlan) com.ibm.websphere.security.auth.WSSubject.doAs(subject,
new java.security.PrivilegedAction<wPlan>() {
public wPlan run() {
wPlan session = null;
try {
Object o = initialContext.lookup(PLAN_EJB_NAME_LONG);
wPlanHome home = (wPlanHome) PortableRemoteObject.narrow(o, wPlanHome.class);
if (home != null) {
session = home.create(remoteServerName);
}
} catch (Exception exc) {
System.err.println("Error getting plan bean: " + exc);
}
return session;
}
}); // end doAs
}
return planBean;
}
public Subject getSubject() {
if (subject == null) {
init();
}
return subject;
}
}
As indicated in another answer, the classic mechanism is to lookup and narrow the home interface.
Get the initial context
final InitialContext initialContext = new InitialContext();
Lookup for the home by jndi name, specifying either the full jndi name
Object obj = initialContext.lookup("ejb/com/ibm/tws/conn/plan/ConnPlanHome");
or you can create e reference in your WAR and use java:comp/env/yourname
Then narrow the home to the home interface class
ConnPlanHome planHome = (ConnPlanHome)PortableRemoteObject.narrow(obj, ConnPlanHome.class);
and then create the EJB remote interface
ConnPlan plan = planHome.create();
The about calls should work for IBM Workload Scheduler distributed.
For IBM Workload Scheduler z/OS the JNDI name and the class names are different:
final InitialContext initialContext = new InitialContext();
String engineName = "XXXX";
Object obj = initialContext.lookup("ejb/com/ibm/tws/zconn/plan/ZConnPlanHome");
ZConnPlanHome planHome = (ZConnPlanHome)PortableRemoteObject.narrow(obj, ZConnPlanHome.class);
ZConnPlan plan = planHome.create(engineName);
User credentials are propagated from the client to the engine, the client need to be authenticated otherwise the engine will reject the request.
If you're trying to access an EJB from a POJO class, then there is nothing more simple than lookup+narrow. However, if the POJO is included in an application (EAR or WAR), then you could declare and lookup an EJB reference (java:comp/ejb/myEJB), and then the container would perform the narrow rather than your code. If you change your code to be a managed class like a servlet, another EJB, or a CDI bean, then you could use #EJB injection, and then you would not even need a lookup.

Java Code - ArrayIndexOutofBoundsException

I have written the following code and keep running into this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at yournamep3.Yournamep3test.main(Yournamep3test.java:23)
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
public class Yournamep3test {
public static void main(String[] args) {
// Check if target file exists
File targetFile = new File(args[0]);
try {
PrintWriter out = new PrintWriter(targetFile);
out.write("\r\nStringed musical Instrument program");
for (int arrayIndex = 0; arrayIndex < 10; arrayIndex++) {
out.write("\r\n\r\n");
out.write("\r\nCreating new Stringed Musical Instrument object now..............");
Yournamep3 violinInstrument = new Yournamep3();
violinInstrument.setNameOfInstrument("Violin # " + (arrayIndex+1));
out.write("\r\nCreated instrument with name - "
+ violinInstrument.getNameOfInstrument());
int num = violinInstrument.getNumberOfStrings();
out.write("\r\nNumber of strings in instrument is " + num);
out.write("\r\nNames of String are ");
String strings[] = violinInstrument.getStringNames();
for (int counter = 0; counter < num; counter++) {
out.write("\r\n" + strings[counter]);
}
out.write("\r\nIs the Instrument playing - "
+ violinInstrument.isPlaying());
out.write("\r\nIs the Instrument tuned - "
+ violinInstrument.isTuned());
out.write("\r\nTuning now.........");
violinInstrument.setTuned(true);
out.write("\r\nIs the Instrument tuned - "
+ violinInstrument.isTuned());
out.write("\r\nCalling the Instrument play method now..");
violinInstrument.startPlayInstrument();
out.write("\r\nIs the Instrument playing - "
+ violinInstrument.isPlaying());
out.write("\r\nStopping playing of instrument..............");
violinInstrument.stopPlayInstrument();
out.write("\r\nIs the Instrument playing - "
+ violinInstrument.isPlaying());
}
out.close();
} catch (IOException e) {
}
}
}
I think the issue is with line 23. Any advice would be appreciated, thanks.
This is the other part of the code yournamep3
public class Yournamep3 {
//fields to determine if the instrument is isTuned,
private boolean isTuned;
//and if the instrument is currently isPlaying.
private boolean isPlaying;
private String name;
private int numberOfStrings = 4; // number of strings
private String nameofStringsInInstrument[] = {"E", "C", "D", "A"}; //an array of string names
//A constructor method that set the isTuned and currently isPlaying fields to false.
public Yournamep3() {
this.isTuned = false;
this.isPlaying = false;
}
/**
* #return the name
*/
public String getNameOfInstrument() {
return name;
}
/**
* #param name the name to set
*/
public void setNameOfInstrument(String nameOfInstrument) {
this.name = nameOfInstrument;
}
// Other methods
public boolean isPlaying() {
return isPlaying;
}
public void setPlaying(boolean playing) {
this.isPlaying = playing;
}
public boolean isTuned() {
return isTuned;
}
public void setTuned(boolean isTuned) {
this.isTuned = isTuned;
}
public void startPlayInstrument() {
System.out.println("The Instrument is now Playing.");
isPlaying = true;
}
public void stopPlayInstrument() {
System.out.println("The Instrument is not Playing anymore.");
isPlaying = false;
}
public void startTuneInstrument() {
System.out.println("The Instrument is Tuned.");
isTuned = true;
}
public void stopTuneInstrument() {
System.out.println("The Instrument is not Tuned.");
isTuned = false;
}
public int getNumberOfStrings() {
return this.numberOfStrings ;
}
public String[] getStringNames() {
return nameofStringsInInstrument;
}
}
I would look at your getStringNames() method for your violinInstrument. It seems to me that it isn't populating your String array properly, or the getNumberOfStrings() method does not give the right number of strings. If you put the code for that up, I can help a bit more.
Line 23 appears to be
Yournamep3 violinInstrument = new Yournamep3();
If that's the case you should check the constructor for Yournamemp3
Since Line 23 is
File targetFile = new File(args [0]);
It indicates that your args object is empty. ArrayIndexOutOfBoundException is thrown to indicate that an array has been accessed with an illegal index. 0 is an illegal index.

How to import an xquery module using Saxon

I am having some troubles running an Xquery with Saxon9HE, which has a reference to an external module.
I would like Saxon to resolve the module with a relative path rather absolute.
the module declaration
module namespace common = "http://my-xquery-utils";
from the main xquery
import module namespace common = "http://my-xquery-utils" at "/home/myself/common.xquery";
from my java code
public class SaxonInvocator {
private static Processor proc = null;
private static XQueryEvaluator xqe = null;
private static DocumentBuilder db = null;
private static StaticQueryContext ctx = null;
/**
* Utility for debug, should not be called outside your IDE
*
* #param args xml, xqFile, xqParameter
*/
public static void main(String[] args) {
XmlObject instance = null;
try {
instance = XmlObject.Factory.parse(new File(args[0]));
} catch (XmlException ex) {
Logger.getLogger(SaxonInvocator.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex){
Logger.getLogger(SaxonInvocator.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.print(transform(instance, args[1], args[2]));
}
public static String transform(XmlObject input, String xqFile, String xqParameter) {
String result = null;
try {
proc = new Processor(false);
proc.getUnderlyingConfiguration().getOptimizer().setOptimizationLevel(0);
ctx = proc.getUnderlyingConfiguration().newStaticQueryContext();
ctx.setModuleURIResolver(new ModuleURIResolver() {
#Override
public StreamSource[] resolve(String moduleURI, String baseURI, String[] locations) throws XPathException {
StreamSource[] modules = new StreamSource[locations.length];
for (int i = 0; i < locations.length; i++) {
modules[i] = new StreamSource(getResourceAsStream(locations[i]));
}
return modules;
}
});
db = proc.newDocumentBuilder();
XQueryCompiler comp = proc.newXQueryCompiler();
XQueryExecutable exp = comp.compile(getResourceAsStream(xqFile));
xqe = exp.load();
ByteArrayInputStream bais = new ByteArrayInputStream(input.xmlText().getBytes("UTF-8"));
StreamSource ss = new StreamSource(bais);
XdmNode node = db.build(ss);
xqe.setExternalVariable(
new QName(xqParameter), node);
result = xqe.evaluate().toString();
} catch (SaxonApiException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public static InputStream getResourceAsStream(String resource) {
InputStream stream = SaxonInvocator.class.getResourceAsStream("/" + resource);
if (stream == null) {
stream = SaxonInvocator.class.getResourceAsStream(resource);
}
if (stream == null) {
stream = SaxonInvocator.class.getResourceAsStream("my/project/" + resource);
}
if (stream == null) {
stream = SaxonInvocator.class.getResourceAsStream("/my/project/" + resource);
}
return stream;
}
}
If a change it into a relative path like
import module namespace common = "http://my-xquery-utils" at "common.xquery";
I get
Error on line 22 column 1
XQST0059: java.io.FileNotFoundException
I am not sure how the ModuleURIResolver should be used.
Saxon questions are best asked on the Saxon forum at http://saxonica.plan.io - questions asked here will probably be noticed eventually but sometimes, like this time, they aren't our first priority.
The basic answer is that for the relative URI to resolve, the base URI needs to be known, which means that you need to ensure that the baseURI property in the XQueryCompiler is set. This happens automatically if you compile the query from a File, but not if you compile it from an InputStream.
If you don't know a suitable base URI to set, the alternative is to write a ModuleURIResolver, which could for example fetch the module by making another call on getResourceAsStream().

Resources