How to config and lookup JNDI in websphere? - ejb

I'm studying EJB now, and I create a simple EJB example in JBOSS and run successfully, here are my steps:
Create an EJB project in myeclipse
Create an interface named FirstEjb
Create FirstEjbBean implemented the FirstEjb interface, and mark the EJB annotations
#Remote
#Stateless
public class FirstEjbBean implements FirstEjb {
#Override
public String saySomething(String name) {
return "Hello, " + name;
}
}
Create a Java project name "EjbClient" in MyEclipse, export the FirstEjb interface as a *.jar and the new Java project reference to it
Add all the jars in directory "client" of JBOSS to EjbClient project
Create a jndi.properties in the Ejb:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
7 .Create class FirstEjbClient.java
public class FirstEjbClient {
public static void main(String[] args) throws NamingException {
InitialContext context = new InitialContext();
FirstEjb ejb = (FirstEjb) context.lookup("FirstEjbBean/remote");
String something = ejb.saySomething("Jimmy.Chen");
System.out.println(something);
}
}
And then I can access the EJB successfully.
The question is, I don't know how to do this same in websphere.
There are some questions:
Do I need to config anything in websphere after deploy the EJB project? Like JNDI??
What jars should I import into the Client project? And those jars are in what directory of websphere?
Do I still need the jndi.properties? And how to write it if needed?
I have search on the internet a lot, but all I found is config the data source in websphere.
Sorry for my poor English, hope there is someone can understand it and provide some help.
Thanks in advance!
Jimmy.Chen

Hello,
try this:
Properties props= new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
props.setProperty(Context.PROVIDER_URL,"corbaloc:iiop:localhost:2809");
Context ctx = new InitialContext(props);
Object homeObject = ctx.lookup("some.package.MyEJBRemote");
MyEJBRemote myEJB = (MyEJBRemote) javax.rmi.PortableRemoteObject.narrow(homeObject, some.package.MyEJBRemote);
However I'm not sure about the jars necessary to import, since you can add WebSphere Application Server X runtime library to the buildpath in Eclipse
WAS runtimes for Eclipse are on http://www.ibmdw.net/wasdev/

When you create an EJB project in Eclipse, an EJB deployment descriptor is created. You have to add all your JNDI resources in it, in the references tab.
And you have to add websphere runtime JARs same as you have added any other JARs.

Related

EF Core in .NET Core library

The main idea is to add a EF Core nuget package to a .NET Core library project and then use that library in a bunch of applications (e.g., ASP.NET Core, Win Service, Console App) without configuring EF in each of them. And, if possible, without adding EF packages to each of them.
I'm wondering if it's possible.
My current problem is that I can't create a database based on the model I have in the library project.
It seems I can't just select the library project in the Package Manager Console and run update-database. It wants me to implement 'IDesignTimeDbContextFactory'.
I'm using .NET Core 2.1. Would it help if I update it to the latest version?
As mentioned by the error, you need to implement IDesignTimeDbContextFactory which is part of the Microsoft.EntityFrameworkCore.Design package so go ahead and install that in your library. Then create a class that implements IDesignTimeDbContextFactory appropriately.
Since you created a .NET Core library, set that as your startup project.
Then in your Package Manager Console, select your library as the Default project and run update-database.
Yes, you can do this.
Make sure you have all the prerequisites installed.
Create a .NET Core Console app
Create a Core Class library for Entity Framework
Reference the Class library from the Console App
Scaffold your database, go to Tools > Package Manager Console
From the dropdown set your default project to your class library so it will scaffold there.
Run this in the console (database first approach): Scaffold-DbContext "Your connecting string here" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models/EF -f
Create a class to get your context
public class Context
{
// See all queries generated by EF in debug window
public static readonly LoggerFactory MyLoggerFactory
= new LoggerFactory(new[] { new DebugLoggerProvider((s, level) => level >= LogLevel.Trace) });
public static DF.Data.Models.EF.YourContext GetContext()
{
var optionsBuilder = new DbContextOptionsBuilder<DF.Data.Models.EF.YourContext>();
optionsBuilder.UseSqlServer(
"Your Connection String").UseLoggerFactory(MyLoggerFactory);
return new DF.Data.Models.EF.YourContext(optionsBuilder.Options);
}
public partial class YourContext : DbContext
{
public YourContext(DbContextOptions optionsBuilderOptions) : base(optionsBuilderOptions)
{
}
}
}
Create a Repository class to store your queries if you would like.
Note: When you scaffold the database again make sure you select the Class library project as the default project from the dropdown. Then set your other project back to the startup project.

Is there a universal config file for .Net Standard 2.0 Class Library?

I have a Class Library that I'm converting to a .Net Standard 2 class library in order to also use in ASP.Net Core 2.0 projects.
The library has always read from a config file items such as SMTP settings, connection strings etc.
In Web Projects it finds these values in web.config.
In Console/WinForms it finds these values in app.config.
Is there an equivalent config file for .Net Core 2.0 projects that "just works" like the previous examples?
I assume the answer is no, but looking for best way to handle this given the library is used across the organization, so maintaining backwards compatibility is important.
Turns out System.Configuration.ConfigurationManager was added back in .NETStandard 2.0.
Just pull it in from nuget and compile the .NETStandard 2.0 class library project.
Then, the library will work across projects using standard config files:
Net Core 2.0 projects use app.config
Web projects work from web.config
Console and Windows apps work with app.config
.Net Core revised configuration approach greatly.
You don't call ConfigurationManager.AppSettings["someSetting"] anymore whenever you need value for some setting. Instead you load configuration on application startup with ConfigurationBuilder. There could be multiple configuration sources (json or/and xml configuration file, environment variables, command line, Azure Key Vault, ...).
Then you build your configuration and pass strongly typed setting objects wrapped into IOption<T> to consuming classes.
Here is a basic idea of how it works:
// Application boostrapping
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddJsonFile("AppSettings.json");
var configuration = configurationBuilder.Build();
// IServiceCollection services
services.AddOptions();
services.Configure<SomeSettings>(configuration.GetSection("SomeSection"));
// Strongly typed settings
public class SomeSettings
{
public string SomeHost { get; set; }
public int SomePort { get; set; }
}
// Settings consumer
public class SomeClient : ISomeClient
{
public SomeClient(IOptions<SomeSettings> someSettings)
{
var host = someSettings.Value.SomeHost;
var port = someSettings.Value.SomePort;
}
}
// AppSettings.json
{
"SomeSection": {
"SomeHost": "localhost",
"SomePort": 25
}
}
For more details check article Configure an ASP.NET Core App.
I'm afraid that it will be difficult (trying to avoid word 'impossible') to maintain backward compatibility.

How to get appsettings from project root to IDesignTimeDbContextFactory implementation in ASP.NET Core 2.0 and EF Core 2.0

I am building an application in ASP.NET Core 2.0 and I am having problems with EntityFramework Migrations.
I have my DbContext in a separate project (SolutionName\ProjectNamePrefix.Data) and therefore I created an implementation for the IDesignTimeDbContextFactory interface.
I wanted to use different connection strings for different environments and I need appsettings.json for that.
So after a quick search I found that I can create a new IConfigurationRoot object inside the CreateDbContext function as shown here:
https://codingblast.com/entityframework-core-idesigntimedbcontextfactory/
I added that and then for testing, tried to run dotnet ef migrations list -c MyContext from the Data project root folder.
Then I got the following error:
The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\dev\*SolutionName*\*ProjectNamePrefix*.Data\bin\Debug\netcoreapp2.0\appsettings.json'.
So, basically, I tried 3 options for getting the correct root path:
Directory.GetCurrentDirectory();
env.ContentRootPath; (IHostingEnvironment object, I found a way to get it here: https://github.com/aspnet/Home/issues/2194)
AppDomain.CurrentDomain.BaseDirectory;
and all of them returned the same ..\bin\debug\netcoreapp2.0\ path. When I run the Data project from VS, then the two first options give me the correct project root folder.
Is there a way to get the correct project content root folder?
Because when I added --verbose to the EF command, it logged out a row:
Using content root 'C:\dev\FitsMeIdentity\FitsMeIdentity.Data\'.
So I understand that EF somehow knows the project root but all the options mentioned above return the path for the already built application.
The only option I found that works is that I change Copy output to root folder to Copy always but found from here: https://www.benday.com/2017/02/17/ef-core-migrations-without-hard-coding-a-connection-string-using-idbcontextfactory/ that it's not a good idea.
At first I even thought about creating a Constructor for the IDesignTimeDbContextFactory implementation which gets IOptions as a parameter but that didn't work, had the same problem as explained here:
Injecting Env Conn String into .NET Core 2.0 w/EF Core DbContext in different class lib than Startup prj & implementing IDesignTimeDbContextFactory
A little late, but here is the solution for those who hate hard-coding connections strings:
internal class MigrationDbContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build();
string connectionString = configuration.GetConnectionString("DefaultConnection");
DbContextOptionsBuilder<AppDbContext> optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
optionsBuilder.UseMySql(connectionString,
ServerVersion.AutoDetect(connectionString),
mySqlOptions =>
mySqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null));
return new AppDbContext(optionsBuilder.Options);
}
}
No. You can't do this, and more to the point: you're not supposed to do this. The whole entire point of IDesignTimeDbContextFactory is that it's a way to get a DbContext instance from in a context where there is no ASP.NET Core framework to work with, i.e. from a class library. If you're running migrations from an ASP.NET Core project, you don't need it, and if you're not, none of the configuration stuff is available.
Additionally, it's only to be used for development, hence the "DesignTime" part of the name. As a result, there's no need for stuff like switching between connection strings for different environments. Just hard-code the connection string as the docs detail.

Not able to parameterize an ejb function

I can write a ejb like this...
#Stateless
public class AnotherBean {
#PersistenceContext(unitName = "VoidJPA-ejbPU")
private EntityManager em;
public void newTest() {
System.out.println("Testing");
}
}
And call it using this from a servlet
#EJB
private AnotherBean nsb;
...
...
nsb.newTest();
But whenever i put a variable into newTest() i cannot access it
public void test(String i)
The servlet and EJB are both deployed but still
the server gives the error
WARNING: StandardWrapperValve[HelloEjb]: PWC1406: Servlet.service() for servlet
HelloEjb threw exception
java.lang.NoSuchMethodError: enew.AnotherBean.newTest(Ljava/lang/String;)V
at jpa.HelloEjb.processRequest(HelloEjb.java:44)
at jpa.HelloEjb.doGet(HelloEjb.java:85)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
.....
........
......
Any Help
Thanks
Pradyut
India
The Servlet clearly doesn't see the version of the Bean with the String parameter at runtime (you might have several versions on the classpath).
This could be a packaging issue, a deployment issue. You need to tell us more about the way you package and deploy your application.
Clean and rebuild your application then deploy again. Also check the dependencies. It seems the EJB contract is not visible to the servlet.
Ya i got it...
In netbeans i had to do the following...
Clean and Build the Ejb Project
Deploy the Ejb Project
Deploy the WebApplication(war) project (and make sure the ejb jar is in libraries which netbeans automatically does and needs no worry).

Getting Context path

I am developing a dynamic web project j2ee web application using eclipse. I have an existing jasper report file in .jrxml format found in web-inf/jasperreports folder. How do I access these files from my java classes in the src folder. I am not even sure if context path is the right term for the root folder of the application so please enlighten me too on this part.
I am using by the way spring webflow. how do i get or initialize the object servlet context
ServletContext.getRealPath method can be used to get the context path. ServletContext.getRealPath("/") returns the webapp root path. Path for WEB-INF/jasperreports would be:
ServletContext sc = getServletContext();
String reportPath = sc.getRealPath("/WEB-INF/jasperreports");
You can initialize you java classes from a Servlet of ServletContextListener where you can get reference for ServletContext by respectively the inherited getServletContext() and the servletContextEvent.getServletContext().

Resources