You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Patrick Savage <pa...@3pillarglobal.com> on 2013/09/18 22:08:25 UTC

XWork injection intermittently skipped

We are using XWork's @Inject in Struts 2.3.1.2 to inject a
DefaultObjectTypeDeterminer into a custom type converter. Since upgrading
from Java 1.6.0_33 to 1.7.0_25, this injection does not occur about half the
time. The other @Inject we use (injecting a ValidatorFactory into a custom
ActionValidatorManager configured by struts.actionValidatorManager in
struts.xml) is still always working. There are no log messages at any log
level that indicate a problem. The container successfully creates the custom
type converter bean as evidenced by the log message
"java.util.List:com.candyland.web.converters.CandylandCollectionConverter
[treated as TypeConverter
com.candyland.web.converters.CandylandCollectionConverter@245f96b0]".

Is it possible that this problem occurs because the getDeclaredMethods
method in Java 7 no longer returns methods in a consistent order
(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7023180)?. Per
https://groups.google.com/forum/#!topic/google-guice/rQD5L2O-Po8, this
causes Guice to inject objects in an inconsistent order so presumably the
Struts container would do the same, but I don't know if that would have any
negative effects.

This is the relevant code:
	xwork-conversion.properties:
	
	
java.util.List=com.candyland.web.converters.CandylandCollectionConverter
	...

	CandylandCollectionConverter.java:
	
	public class CandylandCollectionConverter extends
XWorkBasicConverter {
		private ObjectTypeDeterminer objectTypeDeterminer;

		@Inject
		public void setObjectTypeDeterminer(ObjectTypeDeterminer
det) {
			this.objectTypeDeterminer = det;
			super.setObjectTypeDeterminer(det);
		}
		...
	}

As a workaround, we lazily get the DefaultObjectTypeDeterminer by calling
Dispatcher.getInstance().getContainer().getInstance(ObjectTypeDeterminer.cla
ss). This seems to be a reasonable workaround, but is there a way to fix the
injection?

--
Patrick


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: XWork injection intermittently skipped

Posted by Martin Gainty <mg...@hotmail.com>.
  


> From: patrick.savage@3pillarglobal.com
> To: user@struts.apache.org
> Subject: XWork injection intermittently skipped
> Date: Wed, 18 Sep 2013 16:08:25 -0400
> 
> We are using XWork's @Inject in Struts 2.3.1.2 to inject a
> DefaultObjectTypeDeterminer into a custom type converter. Since upgrading
> from Java 1.6.0_33 to 1.7.0_25, this injection does not occur about half the
> time. The other @Inject we use (injecting a ValidatorFactory into a custom
> ActionValidatorManager configured by struts.actionValidatorManager in
> struts.xml) is still always working. There are no log messages at any log
> level that indicate a problem. The container successfully creates the custom
> type converter bean as evidenced by the log message
> "java.util.List:com.candyland.web.converters.CandylandCollectionConverter
> [treated as TypeConverter
> com.candyland.web.converters.CandylandCollectionConverter@245f96b0]".
 
MG>doubtful if @Inject works all of the time for ValidatorFactory then only some of the time for CollectionConverter
MG>then the inconsistent behaviour is not from Inject but DefaultObjectTypeDeterminer

> Is it possible that this problem occurs because the getDeclaredMethods
> method in Java 7 no longer returns methods in a consistent order
> (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7023180)?. Per
> https://groups.google.com/forum/#!topic/google-guice/rQD5L2O-Po8, this
> causes Guice to inject objects in an inconsistent order so presumably the
MG>Inject is not guice but com.opensymphony.xwork2.inject.Inject
MG>(perhaps you're thinking of Spring?)

> Struts container would do the same, but I don't know if that would have any
> negative effects.
> 
> This is the relevant code:
> xwork-conversion.properties:
> 
> 
> java.util.List=com.candyland.web.converters.CandylandCollectionConverter
> ...
> 
> CandylandCollectionConverter.java:
> 
> public class CandylandCollectionConverter extends
> XWorkBasicConverter {
> private ObjectTypeDeterminer objectTypeDeterminer;
> 
> @Inject
> public void setObjectTypeDeterminer(ObjectTypeDeterminer
> det) {
> this.objectTypeDeterminer = det;
> super.setObjectTypeDeterminer(det);
> }
> ...
> }
> 
> As a workaround, we lazily get the DefaultObjectTypeDeterminer by calling
> Dispatcher.getInstance().getContainer().getInstance(ObjectTypeDeterminer.cla
> ss). This seems to be a reasonable workaround, but is there a way to fix the
> injection?
MG>then your injection happens at last minute when object is referenced instead of class init?
MG>If you desire finer grained control of when objects will be created maybe you will consider Spring AOP ..
MG>with Guice.createInjector...at least you will have more fine grained control WHEN
MG>your objects are created (before main execute(), during execute() or after execute() )
http://blog.japila.pl/2011/01/abstractmodule-bindconstant-inject-and-named-in-google-guice/

> --
> Patrick
MG>Martin

> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
> 
 		 	   		  

Re: XWork injection intermittently skipped

Posted by Lukasz Lenart <lu...@apache.org>.
2013/9/24 Savage, Patrick <pa...@3pillarglobal.com>:
>> How do you declare bean in struts.xml? As this is strange, if all injections
>> are skipped, it must be something else.
>
> We don't actually declare the bean in struts.xml at all. Is that required in
> order for @Inject to inject Struts objects into my bean? This has worked
> without declaring the bean since we upgraded to Struts 2.1.8 in 2010. Should
> I add this to struts.xml?:
>   <bean class="com.candyland.web.converters.CandylandCollectionConverter"/>
>
> Should I also add a bean for our custom validator manager that uses @Inject?
> We currently have this in struts.xml but no <bean>:
>   <constant name="struts.actionValidatorManager"
>             value="com.candyland.web.ReportTemplateValidationManager"/>

You know, Container is a black magic for us and that's why we want to
switch to Guice ;-)

Anyway, I think yes, you should declare your custom converter as a
bean - Container doesn't perform scan of classpath to discover @Inject
annotation. Probably it is a side effect of scanning methods -
Container will create injectors for each method annotated with @Inject
and your convert must be used in some already defined bean - that's
why it use to work.

Regarding 'struts.actionValidatorManager' it should be reference to
bean not to a class, so you should declare a bean with name and then
use that name in 'struts.actionValidatorManager'

<bean name="ccConverter"
class="com.candyland.web.converters.CandylandCollectionConverter"/>
<constant name="struts.actionValidatorManager" value="ccConverter"/>


Regards
-- 
Łukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: XWork injection intermittently skipped

Posted by "Savage, Patrick" <pa...@3pillarglobal.com>.
2013/9/20 Lukasz Lenart [lukaszlenart@apache.org]:
>> I don't think the setter overridding is the problem because I have also
>> tried injecting into a different method (setObjectTypeDeterminerOverride)
>> which didn't work either. Injecting the container doesn't work either
>> because all injections into CandylandCollectionConverter are skipped (I have
>> already tried injecting an ObjectFactory, ReflectionProvider, and a
>> XWorkConverter). I also have already tried composition although the
>> containing converter still inherited from XWorkBasicConverter.
>
> How do you declare bean in struts.xml? As this is strange, if all injections
> are skipped, it must be something else.

We don't actually declare the bean in struts.xml at all. Is that required in
order for @Inject to inject Struts objects into my bean? This has worked
without declaring the bean since we upgraded to Struts 2.1.8 in 2010. Should
I add this to struts.xml?:
  <bean class="com.candyland.web.converters.CandylandCollectionConverter"/>

Should I also add a bean for our custom validator manager that uses @Inject?
We currently have this in struts.xml but no <bean>:
  <constant name="struts.actionValidatorManager" 
            value="com.candyland.web.ReportTemplateValidationManager"/>

--
Patrick


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: XWork injection intermittently skipped

Posted by Lukasz Lenart <lu...@apache.org>.
2013/9/19 Patrick Savage <pa...@3pillarglobal.com>:
> I don't think the setter overridding is the problem because I have also tried injecting into a different method (setObjectTypeDeterminerOverride) which didn't work either. Injecting the container doesn't work either because all injections into CandylandCollectionConverter are skipped (I have already tried injecting an ObjectFactory, ReflectionProvider, and a XWorkConverter). I also have already tried composition although the containing converter still inherited from XWorkBasicConverter.

How do you declare bean in struts.xml? As this is strange, if all
injections are skipped, it must be something else.

> Is our current workaround which lazily calls Dispatcher.getInstance().getContainer().getInstance(ObjectTypeDeterminer.class) a reasonable long-term solution?

Rather no, I don't like such static references, it will be gone sooner
or later ;-)


Regards
-- 
Łukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: XWork injection intermittently skipped

Posted by Patrick Savage <pa...@3pillarglobal.com>.
2013/9/19 Lukasz Lenart [lukaszlenart@apache.org]:
>2013/9/18 Patrick Savage <pa...@3pillarglobal.com>:
>> We are using XWork's @Inject in Struts 2.3.1.2 to inject a
>> DefaultObjectTypeDeterminer into a custom type converter. Since upgrading
>> from Java 1.6.0_33 to 1.7.0_25, this injection does not occur about half the
>> time. The other @Inject we use (injecting a ValidatorFactory into a custom
>> ActionValidatorManager configured by struts.actionValidatorManager in
>> struts.xml) is still always working. There are no log messages at any log
>> level that indicate a problem. The container successfully creates the custom
>> type converter bean as evidenced by the log message
>> "java.util.List:com.candyland.web.converters.CandylandCollectionConverter
>> [treated as TypeConverter
>> com.candyland.web.converters.CandylandCollectionConverter@245f96b0]".
>>
>> Is it possible that this problem occurs because the getDeclaredMethods
>> method in Java 7 no longer returns methods in a consistent order
>> (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7023180)?. Per
>> https://groups.google.com/forum/#!topic/google-guice/rQD5L2O-Po8, this
>> causes Guice to inject objects in an inconsistent order so presumably the
>> Struts container would do the same, but I don't know if that would have any
>> negative effects.
>
>This is strange ... as @Inject is used all over the framework and works fine.
>
>> This is the relevant code:
>>         xwork-conversion.properties:
>>
>>
>> java.util.List=com.candyland.web.converters.CandylandCollectionConverter
>>         ...
>>
>>         CandylandCollectionConverter.java:
>>
>>         public class CandylandCollectionConverter extends
>> XWorkBasicConverter {
>>                 private ObjectTypeDeterminer objectTypeDeterminer;
>>
>>                 @Inject
>>                 public void setObjectTypeDeterminer(ObjectTypeDeterminer
>> det) {
>>                         this.objectTypeDeterminer = det;
>>                         super.setObjectTypeDeterminer(det);
>>                 }
>>                 ...
>>         }
>>
>> As a workaround, we lazily get the DefaultObjectTypeDeterminer by calling
>> Dispatcher.getInstance().getContainer().getInstance(ObjectTypeDeterminer.cla
>> ss). This seems to be a reasonable workaround, but is there a way to fix the
>> injection?
>
>Maybe direct reference to Container would be better solution? And then
>lazy obtain reference to ObjectTypeDeterminer?
>
>@Inject
>public void setContainer(Container container) {
>    objectTypeDeterminer = container.getInstance(ObjectTypeDeterminer.class);
>}
>
>I think the problem is in setter overriding.
>
>What version of Struts do you use? Sometime ago I have split
>XWorkBasicConverter into bunch of small converters which you can
>re-implement and redeclare. Or maybe instead inheritance you can use
>composition?
>
>public class CandylandCollectionConverter implements TypeConverter {
>
>@Inject
>XWorkBasicConverter
>
>@Inject
>ObjectTypeDeterminer
>
>}

I don't think the setter overridding is the problem because I have also tried injecting into a different method (setObjectTypeDeterminerOverride) which didn't work either. Injecting the container doesn't work either because all injections into CandylandCollectionConverter are skipped (I have already tried injecting an ObjectFactory, ReflectionProvider, and a XWorkConverter). I also have already tried composition although the containing converter still inherited from XWorkBasicConverter.

I'm using Struts 2.3.1.2 so I don't have your WW-3762 change in 2.3.3 that split XWorkBasicConverter into smaller converters. But we are planning to upgrade to the latest version soon so I will try that then.

Is our current workaround which lazily calls Dispatcher.getInstance().getContainer().getInstance(ObjectTypeDeterminer.class) a reasonable long-term solution? 

Martin, I know the Struts DI container is not Guice, but it is based on an old version of Guice which is why I suspected that Java 7 change could be related.

--
Patrick


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: XWork injection intermittently skipped

Posted by Lukasz Lenart <lu...@apache.org>.
2013/9/18 Patrick Savage <pa...@3pillarglobal.com>:
> We are using XWork's @Inject in Struts 2.3.1.2 to inject a
> DefaultObjectTypeDeterminer into a custom type converter. Since upgrading
> from Java 1.6.0_33 to 1.7.0_25, this injection does not occur about half the
> time. The other @Inject we use (injecting a ValidatorFactory into a custom
> ActionValidatorManager configured by struts.actionValidatorManager in
> struts.xml) is still always working. There are no log messages at any log
> level that indicate a problem. The container successfully creates the custom
> type converter bean as evidenced by the log message
> "java.util.List:com.candyland.web.converters.CandylandCollectionConverter
> [treated as TypeConverter
> com.candyland.web.converters.CandylandCollectionConverter@245f96b0]".
>
> Is it possible that this problem occurs because the getDeclaredMethods
> method in Java 7 no longer returns methods in a consistent order
> (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7023180)?. Per
> https://groups.google.com/forum/#!topic/google-guice/rQD5L2O-Po8, this
> causes Guice to inject objects in an inconsistent order so presumably the
> Struts container would do the same, but I don't know if that would have any
> negative effects.

This is strange ... as @Inject is used all over the framework and works fine.

> This is the relevant code:
>         xwork-conversion.properties:
>
>
> java.util.List=com.candyland.web.converters.CandylandCollectionConverter
>         ...
>
>         CandylandCollectionConverter.java:
>
>         public class CandylandCollectionConverter extends
> XWorkBasicConverter {
>                 private ObjectTypeDeterminer objectTypeDeterminer;
>
>                 @Inject
>                 public void setObjectTypeDeterminer(ObjectTypeDeterminer
> det) {
>                         this.objectTypeDeterminer = det;
>                         super.setObjectTypeDeterminer(det);
>                 }
>                 ...
>         }
>
> As a workaround, we lazily get the DefaultObjectTypeDeterminer by calling
> Dispatcher.getInstance().getContainer().getInstance(ObjectTypeDeterminer.cla
> ss). This seems to be a reasonable workaround, but is there a way to fix the
> injection?

Maybe direct reference to Container would be better solution? And then
lazy obtain reference to ObjectTypeDeterminer?

@Inject
public void setContainer(Container container) {
    objectTypeDeterminer = container.getInstance(ObjectTypeDeterminer.class);
}

I think the problem is in setter overriding.

What version of Struts do you use? Sometime ago I have split
XWorkBasicConverter into bunch of small converters which you can
re-implement and redeclare. Or maybe instead inheritance you can use
composition?

public class CandylandCollectionConverter implements TypeConverter {

@Inject
XWorkBasicConverter

@Inject
ObjectTypeDeterminer

}


Regards
-- 
Łukasz
+ 48 606 323 122 http://www.lenart.org.pl/

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org