I write a framwork dependecies for projects which use java 17.
And recently I use the framework in a project which use java 17. I need to use reflect to create beans for a interface automatic.
So I write a ClazzUtil class in framework, it has a method to get all the classes under the package where the parameter class is located. like this:
public static List<String> getAllImplClassesByInterface(Class c) {
List<String> returnClassList = new ArrayList<>();
if (c.isInterface()) {
String packageName = c.getPackage().getName();
// System.out.println(packageName);
try {
List<Class<?>> allClass = getClassList(packageName, true, null);
for (int i = 0; i < allClass.size(); i++) {
if (c.isAssignableFrom(allClass.get(i))) {
if (!c.equals(allClass.get(i))) {// 本身加不进去
Class clazz = allClass.get(i);
if (clazz.getAnnotation(Deprecated.class) != null) {
continue;
}
// String cs = allClass.get(i).toString();
// returnClassList.add(cs.substring(cs.indexOf("class ") + 6));
returnClassList.add(clazz.getName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return returnClassList;
}
Then I use it in my business project, and worked for month. But today, the util class return empty list without code change.
I find the interface and the sub class have different module after debug. Then I move the util class to business project.
It work again, amazing!
But I don't know why. Someone can explain this ?
Related
Is it possible to log to the java console?
I've tried to supply an object with a method on it to use for logging but nothing shows up in debug console.
Am I missing something?
window.setMember("mylog", new Console());
execute("mylog.log('11111111'))
public class Console {
public void log(Object ... objects) {
Logger...get..then..log(obj);
}
}
Is there a better way to log to the Java console ?
This is not working.
Unfortunately, my code relies on a number of libraries and I am unable to push the solution to the UI4J repo.
It basically overrides the normal console.log and works similarly. It intentionally avoids to JSON.stringify(object) since circular dependencies can cause serious issues.
The code:
import netscape.javascript.JSObject;
import momomo.com.Opensource.sources.Functional.lambdas.version.interfaces.Lambda;
....
try {
this.page = navigate( IO.toString(file) );
putConsole();
}
finally {
IO.remove(file);
}
private void putConsole() {
// Note that we call log using the entire arguments ( array )
execute("console.log = function() {" +
put(CONSOLE) + ".log(arguments);" +
"};");
}
}
private static final Console CONSOLE = new Console();
public static final class Console {
public void log(JSObject js) {
StringBuilder sb = new StringBuilder();
iterate(js, (o) -> {
sb.append(o).append(" ");
});
$Log.info(Console.class, sb.toString());
}
}
public static void iterate(JSObject js, Lambda.V1<Object> lambda) {
iterate(js, lambda.R1());
}
public static void iterate(JSObject js, Lambda.R1<Boolean, Object> lambda) {
if ( js != null ) {
Object member;
int i = 0;
while (true) {
member = js.getSlot(i);
if ( "undefined".equals(member) || Is.False( lambda.call(member) ) ) {
return;
}
i++;
}
}
}
Outdated but useful Lambda.java reference:
https://github.com/momomo/Opensource/blob/master/src/momomo/com/Opensource/sources/Functional/lambdas/version/interfaces/Lambda.java
Note that put(CONSOLE) call above, basically calls execute("window").setMember("key", new Console()), so there is no magic there, although I have some other logic to achive the same result.
The following is the code where if else is used. If i need to dynamically create a class. how can i do it? is Reflection used ? If so : how can i implement the same using reflection?
public static Pizza getConcretePizza(String PType)
{
Pizza p=null;
if (PType.equals("Cheese"))
{
p=new CheesePizza();
//ResultIng = cp.FetchIng();
} else if (PType.equals("Pepperoni"))
{
p=new PepperoniPizza();
// ResultIng = pp.FetchIng();
}
else if (PType.equals("Clam"))
{
p = new CalmPizza();
//ResultIng = cap.FetchIng();
}
else if (PType.equals("Veggie"))
{
p= new VeggiePizza();
// ResultIng = vp.FetchIng();
}
return(p);
}
I tried getting the answer and finally found the solution.
(INSTEAD OF THE IF _ ELSE WE NEED TO REPLACE THE FOLLWOING CODE)
Class<?> clazz = Class.forName("PizzaTrail." + PType);
Object instance = clazz.newInstance();
p = (Pizza) instance;
return (p);
the above code will resolve the issue of writing the if else and reflection will help calling the class dynamically.
Composable.AddLocation doesn't works for me, even dll is loaded (i can see it in output window), but GetExport(s) return null always.
I used standard example from http://xsockets.net/docs/the-plugin-framework
So this works:
Composable.LoadAssembly(Path.Combine(Helper.PluginsDirectory, "testplugin.dll"));
But this doesn't:
Composable.AddLocation(Helper.PluginsDirectory, SearchOption.AllDirectories, false);
All other code is same.
P.S. Here is solution: Composable.AddLocation begins to work when I deleted XSockets Plug-in Framework dll and dll, which describes plugin interface from Plugins directory.
My guess is this:
You have files in "Helper.PluginsDirectory" that is already loaded by the plugin framework.
If you load one of them twice you will not be able to get the export.
A workaround...
class Program
{
static void Main(string[] args)
{
Composable.RegisterExport<IAnimal>();
//Helper that fix your issue...
Helpers.AddLocation(#"C:\Users\Uffe\Desktop\DynamicAssemblies\Implementation\bin\Debug", SearchOption.AllDirectories);
Composable.ReCompose();
var a = Composable.GetExports<IAnimal>();
foreach (var animal in a)
{
animal.Says();
}
Console.ReadLine();
}
}
public static class Helpers
{
public static void AddLocation(string location, System.IO.SearchOption searchOption)
{
foreach (var assembly in Directory.GetFiles(location, "*.dll", searchOption))
{
AssemblyName verifyName = AssemblyName.GetAssemblyName(assembly);
if(!Composable.LoadedAssemblies.Any(p => p.FullName == verifyName.FullName))
Composable.LoadAssembly(assembly);
}
}
}
I'm trying to find a way to test a abstract class constant that must exist and match/not match a value. Example:
// to be extended by ExternalSDKClild
abstract class ExternalSDK {
const VERSION = '3.1.1.';
}
class foo extends AController {
public function init() {
if ( ExternalSDK::VERSION !== '3.1.1' ) {
throw new Exception('Wrong ExternalSDK version!');
}
$this->setExternalSDKChild(new ExternalSDKChild());
}
}
Limitations... The framework we use doesn't allow dependency injection in the init() method. (Suggestion to refactor the init() method could be the way to go...)
The unit tests and code coverage I have run, cover all but the Exception. I can't figure out a way to make the ExternalSDK::Version to be different from what it is.
All thoughts welcome
First, refactor the call to new into a separate method.
Second, add a method to acquire the version instead of accessing the constant directly. Class constants in PHP are compiled into the file when parsed and cannot be changed.* Since they are accessed statically, there's no way to override it without swapping in a different class declaration with the same name. The only way to do that using standard PHP is to run the test in a separate process which is very expensive.
class ExternalSDK {
const VERSION = '3.1.1';
public function getVersion() {
return static::VERSION;
}
}
class foo extends AController {
public function init() {
$sdk = $this->createSDK();
if ( $sdk->getVersion() !== '3.1.1' ) {
throw new Exception('Wrong ExternalSDK version!');
}
$this->setExternalSDKChild($sdk);
}
public function createSDK() {
return new ExternalSDKChild();
}
}
And now for the unit test.
class NewerSDK extends ExternalSDK {
const VERSION = '3.1.2';
}
/**
* #expectedException Exception
*/
function testInitFailsWhenVersionIsDifferent() {
$sdk = new NewerSDK();
$foo = $this->getMock('foo', array('createSDK'));
$foo->expects($this->once())
->method('createSDK')
->will($this->returnValue($sdk));
$foo->init();
}
*Runkit provides runkit_constant_redefine() which may work here. You'll need to catch the exception manually instead of using #expectedException so you can reset the constant back to the correct value. Or you can do it in tearDown().
function testInitFailsWhenVersionIsDifferent() {
try {
runkit_constant_redefine('ExternalSDK::VERSION', '3.1.0');
$foo = new foo();
$foo->init();
$failed = true;
}
catch (Exception $e) {
$failed = false;
}
runkit_constant_redefine('ExternalSDK::VERSION', '3.1.1');
if ($failed) {
self::fail('Failed to detect incorrect SDK version.');
}
}
I have to support a new input file format in a system which uses Windsor. I also need to support the old version of the input file during a transition phase.
This will probably be repeated in future, and we'll again need to support the new and the next most recent format.
The import processing is handled by a component, and the new version has had significant improvements in the code which makes it lots more efficient compared to the old version. So what I'd like to do is to have the new component and the old component in the system, and dynamically use the new or the old component based upon the file metadata.
Is there a pattern for this type of scenario anyone can suggest?
The fact that you're using Windsor is pretty much irrelevant here. Always strive to find a container-independent solution. Here's one:
interface IImportProcessor {
bool CanHandleVersion(int version);
Stream Import(Stream input);
}
class ImportProcessorVersion1 : IImportProcessor {
public bool CanHandleVersion(int version) {
return version == 1;
}
public Stream Import(Stream input) {
// do stuff
return input;
}
}
class ImportProcessorVersion2 : IImportProcessor {
public bool CanHandleVersion(int version) {
return version == 2;
}
public Stream Import(Stream input) {
// do stuff
return input;
}
}
class MainImportProcessor: IImportProcessor {
private readonly IImportProcessor[] versionSpecificProcessors;
public MainImportProcessor(IImportProcessor[] versionSpecificProcessors) {
this.versionSpecificProcessors = versionSpecificProcessors;
}
public bool CanHandleVersion(int version) {
return versionSpecificProcessors.Any(p => p.CanHandleVersion(version));
}
private int FetchVersion(Stream input) {
// do stuff
return 1;
}
public Stream Import(Stream input) {
int version = FetchVersion(input);
var processor = versionSpecificProcessors.FirstOrDefault(p => p.CanHandleVersion(version));
if (processor == null)
throw new Exception("Unsupported version " + version);
return processor.Import(input);
}
}
Your app would take a dependency on IImportProcessor. The container is wired so that the default implementation of this interface is MainImportProcessor. The container is also wired so that MainImportProcessor gets all other implementations of IImportProcessor.
This way you can add implementations of IImportProcessor and each will be selected when appropriate.
It might be easier to wire things up if MainImportProcessor implements an interface different from IImportProcessor.
Another possibility could be implementing a chain of responsibility.