a list of list value populated in struts2 iterator - list

For my case, it is a little bit trickier. I just have another list in person object, it is called state. like below:
public class People {
private int id;
private String name;
private List<State> states;
// Plus setters/getters
}
public class State {
private int id;
private String stateAbbr;
private String stateName;
public State (String stateAbbr, String stateName) {
this.stateAbbr = stateAbbr;
this.stateName = stateName;
}
// Plus setters/getters
}
Action class:
public class PersonAction extends ActionSupport {
private List<People> peopleList;
public List<People> getPeopleList() {
return peopleList;
}
public void setPeopleList(List<People> peopleList) {
this.peopleList = peopleList;
}
//Initial Load method
#Override
public String execute() {
peopleList = new ArrayList<People>();
int alpha = 65;
for(int i = 0; i < 3 ; i++) {
People people = new People();
people.setId(i);
people.setName(String.valueOf((char)alpha++));
peopleList.add(people);
}
for (People people : peopleList){
State state = new State("BC", "BritishColumbia");
List<State> states = new ArrayList<State>();
states.add(state);
state = new State("AC", "AppleColumbia");
states.add(state);
people.setStates(states);
}
return SUCCESS;
}
//Function that handles the form submit
public String updatePerson() {
for(People people : peopleList) {
System.out.println(people.getId() + ":" + people.getName());
}
return SUCCESS;
}
}
JSP page
<s:form action="doUpdate">
<s:iterator value="peopleList" status="stat" var="people">
<s:textfield value="%{#people.name}"
name="peopleList[%{#stat.index}].name" />
<s:iterator value="states" status="stateStatus" var="personState">
<s:textfield value="%{#personState.stateAbbr}"
name="peopleList[%{#stat.index}].states[%{#stateStatus.index}].stateAbbr" label="Abbr State" />
<br />
</s:iterator>
</s:iterator>
<s:submit value="Submit" />
</s:form>
When I submit this page, I got states is [null] in person, why?

Answer for the new question:
If your State class doesn't have a default constructor, S2/OGNL will not be able to instantiate an empty version of the class.
Provide a default (no-argument) constructor, and the person's states list will be populated.
(Too bad both answers can't be accepted ;)

The state property is a property of a specific person. In this case, you need to "connect" the state to persons[%{#stat.index}], so:
<s:textfield ...
name="persons[%{#stat.index}].states[%{#stateStatus.index}]" .../>
The iterator status variable has an index property that avoids the math you're doing on the IteratorStatus (docs) instance:
<s:textfield ... name="persons[%{#stat.index}].name" />
Also, depending on which version of S2 you're using, you may not need the # character.

Related

thymeleaf custom tag with contents

I'm new to thymeleaf and I'm trying to create a web component. What I want is something as this:
<components:panel><div>hi!</div></components:panel>
translated to something like this:
<div class="panel"><div class="contents"><div>hi!</div></div></div>
I've been trying to extend an AbstractElementTagProcessor, but I can't seem to figure out how to get the tags inside the processed tag:
public class PanelTagProcessor extends AbstractElementTagProcessor {
private static final String ELEMENT_NAME = "panel";
private static final int PRECEDENCE = 10000;
public PanelTagProcessor(final String dialectPrefix) {
super(TemplateMode.HTML, "components", ELEMENT_NAME, true, null, false, PRECEDENCE);
}
#Override
protected void doProcess(ITemplateContext context, IProcessableElementTag tag,
IElementTagStructureHandler structureHandler) {
// How could I surround contents inside the tag with custom nodes?
}
}
I'd be grateful if someone could help me :)
Regards
Luis
First, I don't think it's possible to do with just a AbstractElementTagProcessor. According to the documentation, those kind of processors "execute on open/standalone tag events only (no processors can be applied to close tags), and have no (direct) access to the element body."
I managed to get it working which an AbstractElementModelProcessor ("execute on complete elements, including their bodies, in the form of IModel objects"), so here is what worked for me.
public class PanelTagProcessor extends AbstractElementModelProcessor {
private static final String TAG_NAME = "panel";
private static final int PRECEDENCE = 10000;
public PanelTagProcessor(String dialectPrefix) {
super(TemplateMode.HTML, dialectPrefix, TAG_NAME, true, null, false, PRECEDENCE);
}
#Override
protected void doProcess(ITemplateContext itc, IModel imodel, IElementModelStructureHandler iemsh) {
IModelFactory modelFactory = itc.getModelFactory();
imodel.replace(0, modelFactory.createOpenElementTag("div", "class", "panel"));
imodel.insert(1, modelFactory.createOpenElementTag("div", "class", "contents"));
imodel.insert(imodel.size() - 2, modelFactory.createCloseElementTag("div"));
imodel.replace(imodel.size() - 1, modelFactory.createCloseElementTag("div"));
}
}

How to refer PageReference method from apex test class

I am new to apex, I have created a button to call the apex class through the visual force page.
Here is my visual force page code.
<apex:page standardController="Opportunity"
extensions="myclass"
action="{!autoRun}">
</apex:page>
Here is my apex class.
public class myclass {
private final Opportunity o;
String tmp;
public myclass(ApexPages.StandardController stdController) {
this.o = (Opportunity)stdController.getRecord();
}
public PageReference autoRun() {
String theId = ApexPages.currentPage().getParameters().get('id');
for (Opportunity o:[select id, name, AccountId, from Opportunity where id =:theId]) {
//Create the Order
Order odr = new Order(
OpportunityId=o.id
,AccountId = o.AccountId
,Name = o.Name
,EffectiveDate=Date.today()
,Status='Draft'
);
insert odr;
tmp=odr.id;
}
PageReference pageRef = new PageReference('/' + tmp);
pageRef.setRedirect(true);
return pageRef;
}
}
I want to create test class. I don't know how to refer PageReference autoRun() method from test class. Guys need help if some one can tell me about test class of this apex class.
You will need to configure the StandardController for the inserted Opportunity. Then pass the StandardController to pass to the constructor before calling the method to test.
E.g.
public static testMethod void testAutoRun() {
Opportunity o = new Opportunity();
// TODO: Populate required Opportunity fields here
insert o;
PageReference pref = Page.YourVisualforcePage;
pref.getParameters().put('id', o.id);
Test.setCurrentPage(pref);
ApexPages.StandardController sc = new ApexPages.StandardController(o);
myclass mc = new myclass(sc);
PageReference result = mc.autoRun();
System.assertNotEquals(null, result);
}

How to arrange and assert MustBeCalled for property setter in JustMock

I have a mocked class with a property that has a get and set. My code under test calls the setter to assign a connection string value. My test code mocks the class that contains the property and I add MustBeCalled when I arrange the mock.
ViewModel Code:
public class ClientViewModel
{
private readonly IMgmtDataProvider dataProvider;
public ClientViewModel(IMgmtDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
private string clientConnectionString;
public string ClientConnectionString
{
get { return clientConnectionString; }
set
{
clientConnectionString = value;
if (dataProvider != null)
dataProvider.ClientConnectionString = value;
}
}
}
Test Code:
//Arrange
const string connectionString = "THIS IS MY CONNECTIONSTRING";
var mockedDataProvider = Mock.Create<IMgmtDataProvider>();
Mock.Arrange(() => mockedDataProvider.ClientConnectionString).MustBeCalled();
//Act
var testViewModel = new ClientViewModel(mockedDataProvider);
testViewModel.ClientConnectionString = connectionString;
//Assert
var callCount = Mock.GetTimesCalled(() => mockedDataProvider.ClientConnectinString);
Assert.IsTrue(callCount > 0);
my Mock.Arrange(...).MustBeCalled(); appears to be applied to the getter, not the setter. So, when I call Mock.GetTimesCalled(...), it returns 0. I need to apply the MustBeCalled to the setter instead of the getter. I want to assure the dataprovider's connectionstring is getting set when the viewmodel's connection string gets set. How do I tell JustMock to track how many times a mocked setter is called?
Setters are arranged using the Mock.ArrangeSet() method, like so:
Mock.ArrangeSet(() => mockedDataProvider.ClientConnectionString = Arg.AnyString).MustBeCalled();
....
Mock.Assert(mockedDataProvider); // assert all expectations on this mock
You can also use Mock.AssertSet() as an alternative to the ArrangeSet().MustBeCalled() combo.
And finally, there's the Mock.GetTimesSetCalled() method for getting the number of times that a setter was called.
Check out the documentation on property mocking for examples.

adding an object to a list in play framework

I am new to play, whenever I use list.add(Object) to the list and print the size of the list, it remains 0 !!!
My Method is to like a tutorial, it checks if the logged-in user has liked this tutorial before, if yes, it increments the likeCount of the tutorial by one, and add the tutorial to the like list of the user. If no, it renders that he already likes it.
since the tutorial is not saved in the list, I am not able to check if it is already liked or not !!!
Models:
#Entity
public class RegisteredUser extends Model {
public String name;
#ManyToMany
public List<Tutorial> contributedTutorials;
public RegisteredUser(String name) {
this.name = name;
this.likeList = newArrayList<Tutorial>();
this.save();
}
}
#Entity
public class Tutorial extends Model {
public String Title;
public int likeCount;
public Tutorial(String title) {
this.title = title;
this.likeCount = 0;
}
Controller:
public Tutorials extends Controller {
public static void likeTutorial() {
if (session.get("RegisteredUserId") != null && session.get("tutID") != null ) {
{
long uId = Long.parseLong(session.get("RegisteredUserId"));
RegisteredUser user = RegisteredUser.findById(uId);
long tId = Long.parseLong(session.get("tutID"));
Tutorial tut = Tutorial.findById(tId);
int x = tut.likeCount;
x++;
if (!(user.likeList.contains(tut)))
// to check that this user didn't like this tut before
{
Tutorial.em().createQuery("update Tutorial set likeCount ="+ x +" where id=" +tId).executeUpdate();
tut.refresh();
user.updateLikeList(tut); // THIS IS NOT WORKING!!!
renderText("You have successfully liked this Tutorial " + user.likeList.size());
}
}
renderText("Opps Something went Wrong!!");
}
}
}
The view :
Like
+You don't need to call the this.save() and this.likeList = newArrayList<Tutorial>(); in the constructor. Actually the latter is syntactically wrong.
+Passing the tutorial ID as a session variable is very wrong. You need to pass it as a GET parameter to the action.
+Replace your check with:
// to check that this user didn't like this tut before
if (! user.likeList.contains(tut)) {
// Tutorial.em().createQuery("update Tutorial set likeCount ="+ x +" where id=" +tId).executeUpdate();
// tut.refresh();
// user.updateLikeList(tut); // THIS IS NOT WORKING!!!
tut.likeCount++;
tut.save();
// Since it's a ManyToMany relationship, you only need to add it to one list and the other will reflect properly if mappedBy properly
user.likeList.add(tut); // note that the example you showed uses contributedTutorials not likeList
user.save();
renderText("You have successfully liked this Tutorial " + user.likeList.size());
}
I made all adjustments You mentioned above
And
The mapping in RegisteredUser Model
#ManyToMany
public List<Tutorial> likeList;
and I have added the mapping to Tutorial Model
#ManyToMany
public List<RegisteredUser> likersList;
and adjusted the method in the controller as follows
if (! user.likeList.contains(tut)) {
tut.likeCount++;
//tut.likersList.add(user); // however this raised an error too! at the next line
tut.save();
//as for the likeCount update, it has worked perfectly, Thank You
// Since it's a ManyToMany relationship, you only need to add it to one list and the other will reflect properly if mappedBy properly
//I have modified Model Tutorial as shown above and it didn't work too !
user.likeList.add(tut);
user.save(); // this raised an error!!
renderText("You have successfully liked this Tutorial " + user.likeList.size());
}

How to unmarshal from CSV to Bean with Apache Camel and Bindy?

I'm trying to write my first code with Apache Camel right now. I try to follow the examples from Camel in Action, but I want to use my own example data.
What I want to do
Right now I want to read from a CSV file and get each line as a java bean.
Here is my junit test:
#Test
public void testCsvWithBindy() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:queue.csv");
mock.expectedMessageCount(2);
assertMockEndpointsSatisfied();
CsvBean line1 = mock.getReceivedExchanges().get(0).getIn()
.getBody(CsvBean.class);
assertEquals("row 01", line1.getFirst());
}
public RouteBuilder createRoute() {
return new RouteBuilder() {
public void configure() throws Exception {
context.setTracing(true);
from("file://src/test/resources?noop=true&fileName=test.csv")
.unmarshal().bindy(BindyType.Csv, "my.package.for.csvrecord")
.to("mock:queue.csv");
}
};
}
The CSV contains this:
row 01,row 02,,row 04
row 11, row 12, row 13, row 14
And this is my CsvRecord:
#CsvRecord(separator = ",")
public class CsvBean {
#DataField(pos = 1)
private String first;
#DataField(pos = 2)
private String second;
#DataField(pos = 3)
private String third;
#DataField(pos = 4)
private String fourth;
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getSecond() {
return second;
}
public void setSecond(String second) {
this.second = second;
}
public String getThird() {
return third;
}
public void setThird(String third) {
this.third = third;
}
public String getFourth() {
return fourth;
}
public void setFourth(String fourth) {
this.fourth = fourth;
}
}
My Problem
When I run this test, the context is started and the route is loaded. But nothing is coming through. After about 10s the context is automatically stopped and my test fails. This is the stacktrace:
java.lang.AssertionError: mock://queue.csv Received message count. Expected: <2> but was: <0>
at org.apache.camel.component.mock.MockEndpoint.fail(MockEndpoint.java:1086)
at org.apache.camel.component.mock.MockEndpoint.assertEquals(MockEndpoint.java:1068)
at org.apache.camel.component.mock.MockEndpoint.doAssertIsSatisfied(MockEndpoint.java:367)
at org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied(MockEndpoint.java:346)
at org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied(MockEndpoint.java:334)
at org.apache.camel.component.mock.MockEndpoint.assertIsSatisfied(MockEndpoint.java:172)
at org.apache.camel.test.junit4.CamelTestSupport.assertMockEndpointsSatisfied(CamelTestSupport.java:391)
at my.package.for.unittests.CsvToBeanWithBindyTest.testCsvWithBindy(CsvToBeanWithBindyTest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
Need help with
I guess I'm missing something obvious, maybe something that has to do with the test setup and not so much with my CsvRecord or my route. Can you give me a tip or maybe an URL to a better tutorial? The book is not very helpful at this point... :-(
Again, right after posting my question, I found the answer myself. ;-) Here is a working junit test:
public class CsvToBeanWithBindyTest extends CamelTestSupport {
#Test
public void testCsv() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:queue.csv");
mock.expectedMessageCount(1);
assertMockEndpointsSatisfied();
List line1 = (List) mock.getReceivedExchanges().get(0).getIn()
.getBody();
Map map1 = (Map) line1.get(0);
CsvBean csv1 = (CsvBean) map1.get("my.package.CsvBean");
assertEquals("row 01", csv1.getFirst());
Map map2 = (Map) line1.get(1);
CsvBean csv2 = (CsvBean) map2.get("my.package.CsvBean");
assertEquals("row 11", csv2.getFirst());
}
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
context.setTracing(true);
from("file://src/test/resources?noop=true&fileName=test.csv")
.unmarshal(new BindyCsvDataFormat("my.package"))
.to("mock:queue.csv");
}
};
}
}
The unexpected thing for me is that I get a List from my endpoint route which in turn holds many Maps. Each map has a key my.package.MyBeanClass with the value set to the actual unmarshalled row from my CSV file.