I have this Java class
class Dog {
private String name;
public Dog() {
name = "Fido";
}
public String getName() {
return name;
}
}
And as mentioned here I have performed these steps
1. Compile the class.
mkdir classes
javac -d classes src/Dog.java
2.Add classes to the classpath in your Rails application (an initializer for example).
require 'java'
$CLASSPATH << File.join(Rails.root, "classes")
3.Import the class.
java_import Java::Dog
But still I am not able to access the getName() method in rails 3 with the NoMethodError, but the method is accesible in jRuby.
try making the java class PUBLIC it worked for me.since the default is package-private
Related
Javassist proxyFactory can create proxy at runtime with method interceptor. But how to add method interceptor to a class statically by modifying the class file?
For example, class Foo has 100 methods, before calling any method on an instance of Foo, need to check if the Foo instance is initialized.
public class Foo {
public void methodA() {
...
}
public void methodB() {
...
}
public void methodC() {
...
}
....
}
How to modify the class file to add such method interceptor? One way is to add code at the beginning of each method. Is there a better way?
How about other bytecode tools such as cglib, ....?
There are two options with ByteBuddy to achive this:
use redefine/rebase feature - You can check the details on ByteBuddy tutorial under 'type redefinition'/'type rebasing' tags. Limitation here is that this kind of transformation needs to be done before a target class is loaded.
Java Agent - agents run before class is loaded so they are allowed to modify existing classes. ByteBuddy comes with nice AgentBuilder (tutorial - 'Creating Java agents'). There is also posiblity to install special ByteBuddy agent at runtime (example from mentioned tutorial).
class Foo {
String m() { return "foo"; }
}
class Bar {
String m() { return "bar"; }
}
ByteBuddyAgent.install();
Foo foo = new Foo();
new ByteBuddy()
.redefine(Bar.class)
.name(Foo.class.getName())
.make()
.load(Foo.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
assertThat(foo.m(), is("bar"));
Can homebody help me please to give me a hint how to redefine static methods using byte-buddy 1.6.9 ?
I have tried this :
public class Source {
public static String hello(String name) {return null;}
}
public class Target {
public static String hello(String name) {
return "Hello" + name+ "!";
}
}
String helloWorld = new ByteBuddy()
.redefine(Source.class)
.method(named("hello"))
.intercept(MethodDelegation.to(Target.class))
.make()
.load(getClass().getClassLoader())
.getLoaded()
.newInstance()
.hello("World");
I got following Exception :
Exception in thread "main" java.lang.IllegalStateException: Cannot inject already loaded type: class delegation.Source
Thanks
Classes can only be loaded once by each class loader. In order to replace a method, you would need to use a Java agent to hook into the JVM's HotSwap feature.
Byte Buddy provides a class loading strategy that uses such an agent, use:
.load(Source.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent());
This does however require you to install a Java agent. On a JDK, you can do so programmatically, by ByteBuddyAgent.install() (included in the byte-buddy-agent artifact). On a JVM, you have to specify the agent on the command line.
According COMPOSITION ROOT pattern, I must to construct all dependencies graph as close as possible to the application's entry point.
My architecture is plugin oriented. So, if someone wants to extend my base system he can.
For example, in my base system I have this structure:
View Layer
Services Layer
Data Access Layer
Model Layer
In DAL, I expose some classes like:
IRepository
NHibernateRepository
ProductRepository
So, I'd like if a plugin wants to extend my base Product class to ExtendedProduct, and then create ExtendedProductRepository that inherits from NHibernateRepository.
The question is:
How can instantiate from my base system an instance of NHibernateRepository using NInject?
So, I know the first thing to do is to construct the graph dependencies:
using (var kernel = new StandardKernel())
{
kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom<IRepository>()
.BindAllInterfaces());
}
However, I'm figuring out that when I execute something like:
kernel.GetAll<IRepository>()
It's going to return me a ProductRepository instance, and another ProductExtendedRepository under two IRepository objects.
So, how I can save a ProductExtended object from my base system...?
Another question, would be, how could I inject a object instance in my plugins, or, how can plugins autoinject some instance of base system assembly?
Thanks for all.
I'll appreciate a lot some help.
I use this pattern for my NHibernate based projects:
public interface IRepository<T> : IQueryable<T>
{
T Get(int id);
void Save(T item);
void Delete(T item);
}
public class NHibernateRepository<ModelType> : IRepository<ModelType>
where ModelType : class
{
// implementation
}
then...
public interface IProductRepository : IRepository<Product>
{
// product specific data access methods
}
public class ProductRepository : NHibernateRepository<Product>, IProductRepository
{
// implementation
}
... and in Ninject Module:
Bind(typeof(IRepository<>)).To(typeof(NHibernateRepository<>));
Bind<IProductRepository>().To<ProductRepository>();
then you can either request the base functionality like:
public Constructor(IRepository<Product> repo) { ... }
or specific product repository functionality:
public Constructor(IProductRepository repo) { ... }
your plugins can either get the base functionality and won't have to register anything:
public PluginConstructor(IRepository<ProductExtended> repo { ... }
or create their own repositories and register them in a Ninject module.
Thanks dave.
It's perfect. I'll try it.
However, how could I save or get or update (whichever IRepository methods)... an ExtendedProduct instance from my base system?
Think the follow out:
public interface BasePlugin<T> {...}
In another assembly:
public class PluginExtendedProduct : BasePlugin<ExtendedProduct>
{
public PluginExtendedProduct (IRepository<ExtendedProduct> repo { ... }
}
My headache is how to create an instance of (so, ExtendedProduct) in my base system in order to call methods PluginExtendedProduct that uses an IRepository.
I don't know if I'm explaining myself well...
Thanks for all.
This question already has answers here:
Can a java file have more than one class?
(18 answers)
Closed 8 years ago.
Here's the code :
public class EmployeeTest
{
public static void main(String args[]){
//System.out.println("hello world");
Employee aEmployee = new Employee("David",1000);
System.out.println(aEmployee.getName() + aEmployee.getSalary());
}
}
class Employee // **why can't I put a "public" here**
{
// Constructor
public Employee(String name, double salary)
{
this.name = name;
this.salary = salary;
}
// Methods
public String getName()
{
return this.name;
}
public double getSalary()
{
return this.salary;
}
// instance field
private String name;
private double salary;
}
My question is : in the second class definition's first line, why can't I put a "public" to define it ?
What's the exactly meaning of "public" when using it defines a class ?
This is language feature. There must be only one top-level public class per .java file and public class name must match the source java file name.
Basically, non-public types are not accessible outside the package so if you wish to allow type to be used anywhere then make it public.
Never create a type in default package. (Always use package)
Employee.java
package com.abc.model;
public class Employee{..}
EmployeeTest.java
package com.abc.test;
public class EmployeeTest{ ... }
Because a Java source file can have at most one top-level public class or interface, and the name of the source file must be the same as the name of that class or interface.
That's a rule that the Java compiler of Oracle's JDK imposes.
In Java, there can only be a single public top level class per source file and it needs to be named the same as the file.
This is useful for the compiler when it needs to locate a class definition from outside the package, since it knows the type name, it knows which class file to find the class in. For example. since a jar file is in essence a zip file with class files, this prevents the compiler from having to unzip the entire jar to find a class definition.
The Java language specification §7.6 specifies this as an optional restriction;
If and only if packages are stored in a file system (§7.2), the host
system may choose to enforce the restriction that it is a compile-time
error if a type is not found in a file under a name composed of the
type name plus an extension (such as .java or .jav) if either of the
following is true:
The type is referred to by code in other compilation units of the
package in which the type is declared.
The type is declared public (and therefore is potentially accessible
from code in other packages).
you can define a public class inside a public class which is legal.
public class EmployeeTest
{
public class Employee {
}
}
I'm trying to find a method of passing a constructor argument to the constructors of child classes.
These objects are immutable so I'd prefer to use constructor arguments.
The issue I have encountered is that ConstructorArgument does not inherit to child instantiations and the following statements are not interchangeable:
_parsingProcessor = _kernel.Get<IParsingProcessor>(new ConstructorArgument("dataFilePath", dataFilePath);
and
_parsingProcessor = _kernel.Get<IParsingProcessor>(new Parameter("dataFilePath", dataFilePath, true);
So, how can get an inheritable ConstructorArgument and when does it makes sense, if ever, to new the Parameter class?
Yes, you can do this, but it's probably not what you really want. If the container is not actually responsible for instantiating its own dependencies, then its dependencies probably shouldn't be sharing its constructor arguments - it just doesn't make sense.
I'm pretty sure I know what you're trying to do, and the recommended approach is to create a unique binding specifically for your one container, and use the WhenInjectedInto conditional binding syntax, as in the example below:
public class Hello : IHello
{
private readonly string name;
public Hello(string name)
{
this.name = name;
}
public void SayHello()
{
Console.WriteLine("Hello, {0}!", name);
}
}
This is the class that takes a constructor argument which we want to modify, depending on who is asking for an IHello. Let's say it's this boring container class:
public class MyApp : IApp
{
private readonly IHello hello;
public MyApp(IHello hello)
{
this.hello = hello;
}
public virtual void Run()
{
hello.SayHello();
Console.ReadLine();
}
}
Now, here's how you do up the bindings:
public class MainModule : NinjectModule
{
public override void Load()
{
Bind<IApp>().To<MyApp>();
Bind<IHello>().To<Hello>()
.WithConstructorArgument("name", "Jim");
Bind<IHello>().To<Hello>()
.WhenInjectedInto<MyApp>()
.WithConstructorArgument("name", "Bob");
}
}
Basically all this binding is doing is saying the name should be "Jim" unless it's being requested by Hello, which in this case it is, so instead it will get the name "Bob".
If you are absolutely certain that you truly want cascading behaviour and understand that this is very dangerous and brittle, you can cheat using a method binding. Assuming that we've now added a name argument to the MyApp class for some unspecified purpose, the binding would be:
Bind<IHello>().ToMethod(ctx =>
ctx.Kernel.Get<Hello>(ctx.Request.ParentContext.Parameters
.OfType<ConstructorArgument>()
.Where(c => c.Name == "name")
.First()));
Please, please, make sure you are positive that this is what you want before doing it. It looks easy but it is also very likely to break during a simple refactoring, and 95% of the "customized dependency" scenarios I've seen can be addressed using the WhenInjectedInto binding instead.